@aemforms/af-core 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/README.md +34 -0
- package/lib/BaseNode.d.ts +117 -0
- package/lib/BaseNode.js +368 -0
- package/lib/Checkbox.d.ts +80 -0
- package/lib/Checkbox.js +49 -0
- package/lib/CheckboxGroup.d.ts +30 -0
- package/lib/CheckboxGroup.js +40 -0
- package/lib/Container.d.ts +336 -0
- package/lib/Container.js +279 -0
- package/lib/Field.d.ts +185 -0
- package/lib/Field.js +432 -0
- package/lib/Fieldset.d.ts +31 -0
- package/lib/Fieldset.js +97 -0
- package/lib/FileObject.d.ts +17 -0
- package/lib/FileObject.js +30 -0
- package/lib/FileUpload.d.ts +42 -0
- package/lib/FileUpload.js +299 -0
- package/lib/Form.d.ts +413 -0
- package/lib/Form.js +247 -0
- package/lib/FormInstance.d.ts +26 -0
- package/lib/FormInstance.js +116 -0
- package/lib/FormMetaData.d.ts +11 -0
- package/lib/FormMetaData.js +28 -0
- package/lib/Node.d.ts +12 -0
- package/lib/Node.js +27 -0
- package/lib/Scriptable.d.ts +27 -0
- package/lib/Scriptable.js +216 -0
- package/lib/controller/Controller.d.ts +207 -0
- package/lib/controller/Controller.js +263 -0
- package/lib/controller/EventQueue.d.ts +24 -0
- package/lib/controller/EventQueue.js +99 -0
- package/lib/controller/index.d.ts +1 -0
- package/lib/controller/index.js +24 -0
- package/lib/data/DataGroup.d.ts +25 -0
- package/lib/data/DataGroup.js +74 -0
- package/lib/data/DataValue.d.ts +22 -0
- package/lib/data/DataValue.js +50 -0
- package/lib/data/EmptyDataValue.d.ts +14 -0
- package/lib/data/EmptyDataValue.js +46 -0
- package/lib/index.d.ts +27 -0
- package/lib/index.js +59 -0
- package/lib/rules/FunctionRuntime.d.ts +44 -0
- package/lib/rules/FunctionRuntime.js +271 -0
- package/lib/rules/RuleEngine.d.ts +23 -0
- package/lib/rules/RuleEngine.js +67 -0
- package/lib/types/Json.d.ts +126 -0
- package/lib/types/Json.js +16 -0
- package/lib/types/Model.d.ts +352 -0
- package/lib/types/Model.js +20 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +25 -0
- package/lib/utils/DataRefParser.d.ts +30 -0
- package/lib/utils/DataRefParser.js +249 -0
- package/lib/utils/Fetch.d.ts +7 -0
- package/lib/utils/Fetch.js +29 -0
- package/lib/utils/FormUtils.d.ts +47 -0
- package/lib/utils/FormUtils.js +172 -0
- package/lib/utils/JsonUtils.d.ts +55 -0
- package/lib/utils/JsonUtils.js +128 -0
- package/lib/utils/LogUtils.d.ts +7 -0
- package/lib/utils/LogUtils.js +17 -0
- package/lib/utils/SchemaUtils.d.ts +16 -0
- package/lib/utils/SchemaUtils.js +92 -0
- package/lib/utils/TranslationUtils.d.ts +34 -0
- package/lib/utils/TranslationUtils.js +156 -0
- package/lib/utils/ValidationUtils.d.ts +153 -0
- package/lib/utils/ValidationUtils.js +339 -0
- package/package.json +60 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2022 Adobe, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Your access and use of this software is governed by the Adobe Customer Feedback Program Terms and Conditions or other Beta License Agreement signed by your employer and Adobe, Inc.. This software is NOT open source and may not be used without one of the foregoing licenses. Even with a foregoing license, your access and use of this file is limited to the earlier of (a) 180 days, (b) general availability of the product(s) which utilize this software (i.e. AEM Forms), (c) January 1, 2023, (d) Adobe providing notice to you that you may no longer use the software or that your beta trial has otherwise ended.
|
|
6
|
+
*
|
|
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
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.createTranslationObject = exports.createTranslationObj = exports.addTranslationId = exports.invalidateTranslation = exports.CUSTOM_PROPS_KEY = exports.TRANSLATION_ID = exports.TRANSLATION_TOKEN = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Defines generic utilities to translated form model definition
|
|
13
|
+
*/
|
|
14
|
+
// todo: The API's defined in this file could move to a different package later on
|
|
15
|
+
const types_1 = require("../types");
|
|
16
|
+
/** Token used while creating translation specific properties from `adaptive form specification` */
|
|
17
|
+
exports.TRANSLATION_TOKEN = '##';
|
|
18
|
+
/** Name of the object which holds all translation specific properties */
|
|
19
|
+
exports.TRANSLATION_ID = 'afs:translationIds';
|
|
20
|
+
exports.CUSTOM_PROPS_KEY = 'properties';
|
|
21
|
+
const defaultBcp47LangTags = [
|
|
22
|
+
'de-DE',
|
|
23
|
+
'en-US',
|
|
24
|
+
'es-ES',
|
|
25
|
+
'fr-FR',
|
|
26
|
+
'it-IT',
|
|
27
|
+
'ja-JP',
|
|
28
|
+
'ko-KR',
|
|
29
|
+
'pt-BR',
|
|
30
|
+
'zh-CN',
|
|
31
|
+
'zh-TW'
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
const invalidateTranslation = (input, updates) => {
|
|
37
|
+
types_1.translationProps.forEach((prop) => {
|
|
38
|
+
var _a, _b, _c, _d;
|
|
39
|
+
if (prop in updates && ((_b = (_a = input === null || input === void 0 ? void 0 : input[exports.CUSTOM_PROPS_KEY]) === null || _a === void 0 ? void 0 : _a[exports.TRANSLATION_ID]) === null || _b === void 0 ? void 0 : _b[prop])) {
|
|
40
|
+
(_d = (_c = input === null || input === void 0 ? void 0 : input[exports.CUSTOM_PROPS_KEY]) === null || _c === void 0 ? void 0 : _c[exports.TRANSLATION_ID]) === null || _d === void 0 ? true : delete _d[prop];
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
exports.invalidateTranslation = invalidateTranslation;
|
|
45
|
+
/**
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
const addTranslationId = (input, additionalTranslationProps = []) => {
|
|
49
|
+
// don't create a schema copy, add it to the existing
|
|
50
|
+
const model = input;
|
|
51
|
+
const transProps = [...types_1.translationProps, ...additionalTranslationProps];
|
|
52
|
+
_createTranslationId(model, '', transProps);
|
|
53
|
+
return model;
|
|
54
|
+
};
|
|
55
|
+
exports.addTranslationId = addTranslationId;
|
|
56
|
+
/**
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
const _createTranslationId = (input, path, transProps) => {
|
|
60
|
+
Object.entries(input).forEach(([key, value]) => {
|
|
61
|
+
if (typeof value == 'object') {
|
|
62
|
+
_createTranslationId(value, ((key === 'items') ? path : `${path === '' ? path : path + exports.TRANSLATION_TOKEN}${key}${exports.TRANSLATION_TOKEN}${Math.floor(Math.random() * 10000) + 1}`), transProps);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// set it only if either of type or fieldType properties is present
|
|
66
|
+
if ('type' in input ||
|
|
67
|
+
'fieldType' in input) {
|
|
68
|
+
for (const transProp of transProps) {
|
|
69
|
+
// if property exist add it
|
|
70
|
+
if (input[transProp] != null) {
|
|
71
|
+
// if translation id is not yet set, set it
|
|
72
|
+
if (!(exports.CUSTOM_PROPS_KEY in input)) {
|
|
73
|
+
input[exports.CUSTOM_PROPS_KEY] = {};
|
|
74
|
+
}
|
|
75
|
+
if (!(exports.TRANSLATION_ID in input[exports.CUSTOM_PROPS_KEY])) {
|
|
76
|
+
input[exports.CUSTOM_PROPS_KEY][exports.TRANSLATION_ID] = {};
|
|
77
|
+
}
|
|
78
|
+
// if transprop is not yet set, set it
|
|
79
|
+
// this is done to prevent overwrite
|
|
80
|
+
if (!(transProp in input[exports.CUSTOM_PROPS_KEY][exports.TRANSLATION_ID])) {
|
|
81
|
+
input[exports.CUSTOM_PROPS_KEY][exports.TRANSLATION_ID][transProp] = `${path}${exports.TRANSLATION_TOKEN}${transProp}${exports.TRANSLATION_TOKEN}${Math.floor(Math.random() * 10000) + 1}`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* @param input
|
|
91
|
+
* @param translationObj
|
|
92
|
+
* @param translationProps
|
|
93
|
+
* @private
|
|
94
|
+
*/
|
|
95
|
+
const _createTranslationObj = (input, translationObj, translationProps) => {
|
|
96
|
+
Object.values(input).forEach((value) => {
|
|
97
|
+
var _a, _b;
|
|
98
|
+
if (typeof value == 'object') {
|
|
99
|
+
_createTranslationObj(value, translationObj, translationProps);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
for (const translationProp of translationProps) {
|
|
103
|
+
if (translationProp in input && ((_b = (_a = input === null || input === void 0 ? void 0 : input[exports.CUSTOM_PROPS_KEY]) === null || _a === void 0 ? void 0 : _a[exports.TRANSLATION_ID]) === null || _b === void 0 ? void 0 : _b[translationProp])) {
|
|
104
|
+
// todo: right now we create only for english
|
|
105
|
+
if (input[translationProp] instanceof Array) {
|
|
106
|
+
input[translationProp].forEach((item, index) => {
|
|
107
|
+
if (typeof item === 'string') { // only if string, then convert, since values can also be boolean
|
|
108
|
+
// @ts-ignore
|
|
109
|
+
translationObj[`${input[exports.CUSTOM_PROPS_KEY][exports.TRANSLATION_ID][translationProp]}${exports.TRANSLATION_TOKEN}${index}`] = item;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// @ts-ignore
|
|
115
|
+
translationObj[`${input[exports.CUSTOM_PROPS_KEY][exports.TRANSLATION_ID][translationProp]}`] = input[translationProp];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* @param input
|
|
124
|
+
* @param additionalTranslationProps
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
const createTranslationObj = (input, additionalTranslationProps = []) => {
|
|
128
|
+
const obj = {};
|
|
129
|
+
const transProps = [...types_1.translationProps, ...additionalTranslationProps];
|
|
130
|
+
_createTranslationObj(input, obj, transProps);
|
|
131
|
+
return obj;
|
|
132
|
+
};
|
|
133
|
+
exports.createTranslationObj = createTranslationObj;
|
|
134
|
+
/**
|
|
135
|
+
* Creates translation object with [BCP 47](https://tools.ietf.org/search/bcp47) language tags as key and value is a translation object. Key of translation object is
|
|
136
|
+
* generated based on the form hierarchy and it is separated by "##" token to signify that the id is machine generated (ie its not a human generated string)
|
|
137
|
+
* @param input form model definition
|
|
138
|
+
* @param additionalTranslationProps optional properties which needs to be translated, by default, only OOTB properties of form model definition is translated
|
|
139
|
+
* @param bcp47LangTags optional additional language tags
|
|
140
|
+
* @returns translation object for each bcp 47 language tag
|
|
141
|
+
*/
|
|
142
|
+
const createTranslationObject = (input, additionalTranslationProps = [], bcp47LangTags = []) => {
|
|
143
|
+
const transProps = [...types_1.translationProps, ...additionalTranslationProps];
|
|
144
|
+
// create a copy of the input
|
|
145
|
+
const inputCopy = JSON.parse(JSON.stringify(input));
|
|
146
|
+
const obj = (0, exports.createTranslationObj)((0, exports.addTranslationId)(inputCopy), transProps);
|
|
147
|
+
const langTags = [...defaultBcp47LangTags, ...bcp47LangTags];
|
|
148
|
+
const allLangs = {};
|
|
149
|
+
for (const langTag of langTags) {
|
|
150
|
+
// todo: added temporarily to test
|
|
151
|
+
// todo: need to fix this as per machine translation
|
|
152
|
+
allLangs[langTag] = JSON.parse(JSON.stringify(obj));
|
|
153
|
+
}
|
|
154
|
+
return [inputCopy, allLangs];
|
|
155
|
+
};
|
|
156
|
+
exports.createTranslationObject = createTranslationObject;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/** Validation result type **/
|
|
2
|
+
declare type ValidationResult = {
|
|
3
|
+
valid: boolean;
|
|
4
|
+
value: any;
|
|
5
|
+
};
|
|
6
|
+
export declare const isDataUrl: (str: string) => boolean;
|
|
7
|
+
export declare const ValidConstraints: {
|
|
8
|
+
date: string[];
|
|
9
|
+
string: string[];
|
|
10
|
+
number: string[];
|
|
11
|
+
array: string[];
|
|
12
|
+
file: string[];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Implementation of all constraints defined by `adaptive form specification`
|
|
16
|
+
*/
|
|
17
|
+
export declare const Constraints: {
|
|
18
|
+
/**
|
|
19
|
+
* Implementation of type constraint
|
|
20
|
+
* @param constraint `type` property of the form object
|
|
21
|
+
* @param inputVal value of the form object
|
|
22
|
+
* @return {@link ValidationResult | validation result}
|
|
23
|
+
*/
|
|
24
|
+
type: (constraint: string, inputVal: any) => ValidationResult;
|
|
25
|
+
/**
|
|
26
|
+
* Implementation of format constraint
|
|
27
|
+
* @param constraint `format` property of the form object
|
|
28
|
+
* @param input value of the form object
|
|
29
|
+
* @return {@link ValidationResult | validation result}
|
|
30
|
+
*/
|
|
31
|
+
format: (constraint: string, input: string) => {
|
|
32
|
+
valid: boolean;
|
|
33
|
+
value: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Implementation of minimum constraint
|
|
37
|
+
* @param constraint `minimum` property of the form object
|
|
38
|
+
* @param value value of the form object
|
|
39
|
+
* @return {@link ValidationResult | validation result}
|
|
40
|
+
*/
|
|
41
|
+
minimum: (constraint: number, value: number) => {
|
|
42
|
+
valid: boolean;
|
|
43
|
+
value: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Implementation of maximum constraint
|
|
47
|
+
* @param constraint `maximum` property of the form object
|
|
48
|
+
* @param value value of the form object
|
|
49
|
+
* @return {@link ValidationResult | validation result}
|
|
50
|
+
*/
|
|
51
|
+
maximum: (constraint: number, value: number) => {
|
|
52
|
+
valid: boolean;
|
|
53
|
+
value: number;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Implementation of exclusiveMinimum constraint
|
|
57
|
+
* @param constraint `minimum` property of the form object
|
|
58
|
+
* @param value value of the form object
|
|
59
|
+
* @return {@link ValidationResult | validation result}
|
|
60
|
+
*/
|
|
61
|
+
exclusiveMinimum: (constraint: number, value: number) => {
|
|
62
|
+
valid: boolean;
|
|
63
|
+
value: number;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Implementation of exclusiveMaximum constraint
|
|
67
|
+
* @param constraint `maximum` property of the form object
|
|
68
|
+
* @param value value of the form object
|
|
69
|
+
* @return {@link ValidationResult | validation result}
|
|
70
|
+
*/
|
|
71
|
+
exclusiveMaximum: (constraint: number, value: number) => {
|
|
72
|
+
valid: boolean;
|
|
73
|
+
value: number;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Implementation of the minItems constraint
|
|
77
|
+
* @param constraint `minItems` constraint from object
|
|
78
|
+
* @param value value of the form object
|
|
79
|
+
*/
|
|
80
|
+
minItems: <T>(constraint: number, value: T[]) => {
|
|
81
|
+
valid: boolean;
|
|
82
|
+
value: T[];
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Implementation of the maxItems constraint
|
|
86
|
+
* @param constraint `maxItems` constraint from object
|
|
87
|
+
* @param value value of the form object
|
|
88
|
+
*/
|
|
89
|
+
maxItems: <T_1>(constraint: number, value: T_1[]) => {
|
|
90
|
+
valid: boolean;
|
|
91
|
+
value: T_1[];
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Implementation of the uniqueItems constraint
|
|
95
|
+
* @param constraint `uniqueItems` constraint from object
|
|
96
|
+
* @param value value of the form object
|
|
97
|
+
*/
|
|
98
|
+
uniqueItems: <T_2>(constraint: boolean, value: T_2[]) => {
|
|
99
|
+
valid: boolean;
|
|
100
|
+
value: T_2[];
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Implementation of minLength constraint
|
|
104
|
+
* @param constraint `minLength` property of the form object
|
|
105
|
+
* @param value value of the form object
|
|
106
|
+
* @return {@link ValidationResult | validation result}
|
|
107
|
+
*/
|
|
108
|
+
minLength: (constraint: number, value: string) => {
|
|
109
|
+
value: string;
|
|
110
|
+
valid: boolean;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Implementation of maxLength constraint
|
|
114
|
+
* @param constraint `maxLength` property of the form object
|
|
115
|
+
* @param value value of the form object
|
|
116
|
+
* @return {@link ValidationResult | validation result}
|
|
117
|
+
*/
|
|
118
|
+
maxLength: (constraint: number, value: string) => {
|
|
119
|
+
value: string;
|
|
120
|
+
valid: boolean;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Implementation of pattern constraint
|
|
124
|
+
* @param constraint `pattern` property of the form object
|
|
125
|
+
* @param value value of the form object
|
|
126
|
+
* @return {@link ValidationResult | validation result}
|
|
127
|
+
*/
|
|
128
|
+
pattern: (constraint: RegExp | string, value: string) => {
|
|
129
|
+
valid: boolean;
|
|
130
|
+
value: string;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Implementation of required constraint
|
|
134
|
+
* @param constraint `required` property of the form object
|
|
135
|
+
* @param value value of the form object
|
|
136
|
+
* @return {@link ValidationResult | validation result}
|
|
137
|
+
*/
|
|
138
|
+
required: (constraint: boolean, value: any) => {
|
|
139
|
+
valid: boolean;
|
|
140
|
+
value: any;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Implementation of enum constraint
|
|
144
|
+
* @param constraint `enum` property of the form object
|
|
145
|
+
* @param value value of the form object
|
|
146
|
+
* @return {@link ValidationResult | validation result}
|
|
147
|
+
*/
|
|
148
|
+
enum: (constraint: any[], value: any) => {
|
|
149
|
+
valid: boolean;
|
|
150
|
+
value: any;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
export {};
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2022 Adobe, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Your access and use of this software is governed by the Adobe Customer Feedback Program Terms and Conditions or other Beta License Agreement signed by your employer and Adobe, Inc.. This software is NOT open source and may not be used without one of the foregoing licenses. Even with a foregoing license, your access and use of this file is limited to the earlier of (a) 180 days, (b) general availability of the product(s) which utilize this software (i.e. AEM Forms), (c) January 1, 2023, (d) Adobe providing notice to you that you may no longer use the software or that your beta trial has otherwise ended.
|
|
6
|
+
*
|
|
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
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.Constraints = exports.ValidConstraints = exports.isDataUrl = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Defines generic utilities to validate form runtime model based on the constraints defined
|
|
13
|
+
* as per `adaptive form specification`
|
|
14
|
+
*/
|
|
15
|
+
// issue with import
|
|
16
|
+
//import {FieldJson, isFileObject} from '../types';
|
|
17
|
+
const dateRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
|
|
18
|
+
const dataUrlRegex = /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/;
|
|
19
|
+
const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
20
|
+
const daysInMonth = (leapYear, month) => {
|
|
21
|
+
if (leapYear && month == 2) {
|
|
22
|
+
return 29;
|
|
23
|
+
}
|
|
24
|
+
return days[month - 1];
|
|
25
|
+
};
|
|
26
|
+
const isLeapYear = (year) => {
|
|
27
|
+
return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
|
|
28
|
+
};
|
|
29
|
+
const isDataUrl = (str) => {
|
|
30
|
+
return dataUrlRegex.exec(str.trim()) != null;
|
|
31
|
+
};
|
|
32
|
+
exports.isDataUrl = isDataUrl;
|
|
33
|
+
/**
|
|
34
|
+
* Checks whether inputVal is valid number value or not
|
|
35
|
+
*
|
|
36
|
+
* ```
|
|
37
|
+
* const x = checkNumber('12')
|
|
38
|
+
* ```
|
|
39
|
+
* would return
|
|
40
|
+
* ```
|
|
41
|
+
* {
|
|
42
|
+
* value : 12,
|
|
43
|
+
* valid : true
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
* @param inputVal input value
|
|
47
|
+
* @returns {@link ValidationResult | Validation result}
|
|
48
|
+
*/
|
|
49
|
+
const checkNumber = (inputVal) => {
|
|
50
|
+
let value = parseFloat(inputVal);
|
|
51
|
+
const valid = !isNaN(value);
|
|
52
|
+
if (!valid) {
|
|
53
|
+
value = inputVal;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
value, valid
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Wraps a non-null value and not an array value into an array
|
|
61
|
+
* @param inputVal input value
|
|
62
|
+
* @returns wraps the input value into an array
|
|
63
|
+
*/
|
|
64
|
+
const toArray = (inputVal) => {
|
|
65
|
+
if (inputVal != null && !(inputVal instanceof Array)) {
|
|
66
|
+
return [inputVal];
|
|
67
|
+
}
|
|
68
|
+
return inputVal;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Checks whether inputVal is valid boolean value or not
|
|
72
|
+
*
|
|
73
|
+
* ```
|
|
74
|
+
* const x = checkBool('false')
|
|
75
|
+
* ```
|
|
76
|
+
* would return
|
|
77
|
+
* ```
|
|
78
|
+
* {
|
|
79
|
+
* value : false,
|
|
80
|
+
* valid : true
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
* @param inputVal input value
|
|
84
|
+
* @returns {@link ValidationResult | Validation result}
|
|
85
|
+
*/
|
|
86
|
+
const checkBool = (inputVal) => {
|
|
87
|
+
const valid = typeof inputVal === 'boolean' || inputVal === 'true' || inputVal === 'false';
|
|
88
|
+
const value = typeof inputVal === 'boolean' ? inputVal : (valid ? inputVal === 'true' : inputVal);
|
|
89
|
+
return { valid, value };
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Validates an array of values using a validator function.
|
|
93
|
+
* @param inputVal
|
|
94
|
+
* @param validatorFn
|
|
95
|
+
* @return an array containing two arrays, the first one with all the valid values and the second one with one invalid
|
|
96
|
+
* value (if there is).
|
|
97
|
+
*/
|
|
98
|
+
const partitionArray = (inputVal, validatorFn) => {
|
|
99
|
+
const value = toArray(inputVal);
|
|
100
|
+
if (value == null) {
|
|
101
|
+
return [[], [value]];
|
|
102
|
+
}
|
|
103
|
+
return value.reduce((acc, x) => {
|
|
104
|
+
if (acc[1].length == 0) {
|
|
105
|
+
const r = validatorFn(x);
|
|
106
|
+
const index = r.valid ? 0 : 1;
|
|
107
|
+
acc[index].push(r.value);
|
|
108
|
+
}
|
|
109
|
+
return acc;
|
|
110
|
+
}, [[], []]);
|
|
111
|
+
};
|
|
112
|
+
exports.ValidConstraints = {
|
|
113
|
+
date: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'format'],
|
|
114
|
+
string: ['minLength', 'maxLength', 'pattern'],
|
|
115
|
+
number: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
|
|
116
|
+
array: ['minItems', 'maxItems', 'uniqueItems'],
|
|
117
|
+
file: ['accept', 'maxFileSize']
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Implementation of all constraints defined by `adaptive form specification`
|
|
121
|
+
*/
|
|
122
|
+
exports.Constraints = {
|
|
123
|
+
/**
|
|
124
|
+
* Implementation of type constraint
|
|
125
|
+
* @param constraint `type` property of the form object
|
|
126
|
+
* @param inputVal value of the form object
|
|
127
|
+
* @return {@link ValidationResult | validation result}
|
|
128
|
+
*/
|
|
129
|
+
type: (constraint, inputVal) => {
|
|
130
|
+
let value = inputVal;
|
|
131
|
+
if (inputVal == undefined) {
|
|
132
|
+
return {
|
|
133
|
+
valid: true,
|
|
134
|
+
value: inputVal
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
let valid = true, res;
|
|
138
|
+
switch (constraint) {
|
|
139
|
+
case 'string':
|
|
140
|
+
valid = true;
|
|
141
|
+
value = inputVal.toString();
|
|
142
|
+
break;
|
|
143
|
+
case 'string[]':
|
|
144
|
+
value = toArray(inputVal);
|
|
145
|
+
break;
|
|
146
|
+
case 'number':
|
|
147
|
+
res = checkNumber(inputVal);
|
|
148
|
+
value = res.value;
|
|
149
|
+
valid = res.valid;
|
|
150
|
+
break;
|
|
151
|
+
case 'boolean':
|
|
152
|
+
res = checkBool(inputVal);
|
|
153
|
+
valid = res.valid;
|
|
154
|
+
value = res.value;
|
|
155
|
+
break;
|
|
156
|
+
case 'integer':
|
|
157
|
+
value = parseFloat(inputVal);
|
|
158
|
+
valid = !isNaN(value) && Math.round(value) === value;
|
|
159
|
+
if (!valid) {
|
|
160
|
+
value = inputVal;
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
case 'file' || 'file[]':
|
|
164
|
+
valid = true;
|
|
165
|
+
//valid = isFileObject(value);
|
|
166
|
+
if (!valid) {
|
|
167
|
+
value = inputVal;
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
case 'number[]':
|
|
171
|
+
res = partitionArray(inputVal, checkNumber);
|
|
172
|
+
valid = res[1].length === 0;
|
|
173
|
+
value = valid ? res[0] : inputVal;
|
|
174
|
+
break;
|
|
175
|
+
case 'boolean[]':
|
|
176
|
+
res = partitionArray(inputVal, checkBool);
|
|
177
|
+
valid = res[1].length === 0;
|
|
178
|
+
value = valid ? res[0] : inputVal;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
valid,
|
|
183
|
+
value
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
/**
|
|
187
|
+
* Implementation of format constraint
|
|
188
|
+
* @param constraint `format` property of the form object
|
|
189
|
+
* @param input value of the form object
|
|
190
|
+
* @return {@link ValidationResult | validation result}
|
|
191
|
+
*/
|
|
192
|
+
format: (constraint, input) => {
|
|
193
|
+
let valid = true;
|
|
194
|
+
const value = input;
|
|
195
|
+
let res;
|
|
196
|
+
switch (constraint) {
|
|
197
|
+
case 'date':
|
|
198
|
+
res = dateRegex.exec(input.trim());
|
|
199
|
+
if (res != null) {
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
201
|
+
const [match, year, month, date] = res;
|
|
202
|
+
const [nMonth, nDate] = [+month, +date];
|
|
203
|
+
const leapYear = isLeapYear(+year);
|
|
204
|
+
valid = (nMonth >= 1 && nMonth <= 12) &&
|
|
205
|
+
(nDate >= 1 && nDate <= daysInMonth(leapYear, nMonth));
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
valid = false;
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
case 'data-url':
|
|
212
|
+
// todo: input is of type file, do we need this format ? since value is always of type file object
|
|
213
|
+
//res = dataUrlRegex.exec(input.trim());
|
|
214
|
+
//valid = res != null;
|
|
215
|
+
valid = true;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
return { valid, value };
|
|
219
|
+
},
|
|
220
|
+
//todo : add support for date
|
|
221
|
+
/**
|
|
222
|
+
* Implementation of minimum constraint
|
|
223
|
+
* @param constraint `minimum` property of the form object
|
|
224
|
+
* @param value value of the form object
|
|
225
|
+
* @return {@link ValidationResult | validation result}
|
|
226
|
+
*/
|
|
227
|
+
minimum: (constraint, value) => {
|
|
228
|
+
return { valid: value >= constraint, value };
|
|
229
|
+
},
|
|
230
|
+
//todo : add support for date
|
|
231
|
+
/**
|
|
232
|
+
* Implementation of maximum constraint
|
|
233
|
+
* @param constraint `maximum` property of the form object
|
|
234
|
+
* @param value value of the form object
|
|
235
|
+
* @return {@link ValidationResult | validation result}
|
|
236
|
+
*/
|
|
237
|
+
maximum: (constraint, value) => {
|
|
238
|
+
return { valid: value <= constraint, value };
|
|
239
|
+
},
|
|
240
|
+
/**
|
|
241
|
+
* Implementation of exclusiveMinimum constraint
|
|
242
|
+
* @param constraint `minimum` property of the form object
|
|
243
|
+
* @param value value of the form object
|
|
244
|
+
* @return {@link ValidationResult | validation result}
|
|
245
|
+
*/
|
|
246
|
+
exclusiveMinimum: (constraint, value) => {
|
|
247
|
+
return { valid: value > constraint, value };
|
|
248
|
+
},
|
|
249
|
+
//todo : add support for date
|
|
250
|
+
/**
|
|
251
|
+
* Implementation of exclusiveMaximum constraint
|
|
252
|
+
* @param constraint `maximum` property of the form object
|
|
253
|
+
* @param value value of the form object
|
|
254
|
+
* @return {@link ValidationResult | validation result}
|
|
255
|
+
*/
|
|
256
|
+
exclusiveMaximum: (constraint, value) => {
|
|
257
|
+
return { valid: value < constraint, value };
|
|
258
|
+
},
|
|
259
|
+
/**
|
|
260
|
+
* Implementation of the minItems constraint
|
|
261
|
+
* @param constraint `minItems` constraint from object
|
|
262
|
+
* @param value value of the form object
|
|
263
|
+
*/
|
|
264
|
+
minItems: (constraint, value) => {
|
|
265
|
+
return { valid: (value instanceof Array) && value.length >= constraint, value };
|
|
266
|
+
},
|
|
267
|
+
/**
|
|
268
|
+
* Implementation of the maxItems constraint
|
|
269
|
+
* @param constraint `maxItems` constraint from object
|
|
270
|
+
* @param value value of the form object
|
|
271
|
+
*/
|
|
272
|
+
maxItems: (constraint, value) => {
|
|
273
|
+
return { valid: (value instanceof Array) && value.length <= constraint, value };
|
|
274
|
+
},
|
|
275
|
+
/**
|
|
276
|
+
* Implementation of the uniqueItems constraint
|
|
277
|
+
* @param constraint `uniqueItems` constraint from object
|
|
278
|
+
* @param value value of the form object
|
|
279
|
+
*/
|
|
280
|
+
uniqueItems: (constraint, value) => {
|
|
281
|
+
return { valid: !constraint || ((value instanceof Array) && value.length === new Set(value).size), value };
|
|
282
|
+
},
|
|
283
|
+
/**
|
|
284
|
+
* Implementation of minLength constraint
|
|
285
|
+
* @param constraint `minLength` property of the form object
|
|
286
|
+
* @param value value of the form object
|
|
287
|
+
* @return {@link ValidationResult | validation result}
|
|
288
|
+
*/
|
|
289
|
+
minLength: (constraint, value) => {
|
|
290
|
+
return Object.assign(Object.assign({}, exports.Constraints.minimum(constraint, typeof value === 'string' ? value.length : 0)), { value });
|
|
291
|
+
},
|
|
292
|
+
/**
|
|
293
|
+
* Implementation of maxLength constraint
|
|
294
|
+
* @param constraint `maxLength` property of the form object
|
|
295
|
+
* @param value value of the form object
|
|
296
|
+
* @return {@link ValidationResult | validation result}
|
|
297
|
+
*/
|
|
298
|
+
maxLength: (constraint, value) => {
|
|
299
|
+
return Object.assign(Object.assign({}, exports.Constraints.maximum(constraint, typeof value === 'string' ? value.length : 0)), { value });
|
|
300
|
+
},
|
|
301
|
+
/**
|
|
302
|
+
* Implementation of pattern constraint
|
|
303
|
+
* @param constraint `pattern` property of the form object
|
|
304
|
+
* @param value value of the form object
|
|
305
|
+
* @return {@link ValidationResult | validation result}
|
|
306
|
+
*/
|
|
307
|
+
pattern: (constraint, value) => {
|
|
308
|
+
let regex;
|
|
309
|
+
if (typeof constraint === 'string') {
|
|
310
|
+
regex = new RegExp(constraint);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
regex = constraint;
|
|
314
|
+
}
|
|
315
|
+
return { valid: regex.test(value), value };
|
|
316
|
+
},
|
|
317
|
+
/**
|
|
318
|
+
* Implementation of required constraint
|
|
319
|
+
* @param constraint `required` property of the form object
|
|
320
|
+
* @param value value of the form object
|
|
321
|
+
* @return {@link ValidationResult | validation result}
|
|
322
|
+
*/
|
|
323
|
+
required: (constraint, value) => {
|
|
324
|
+
const valid = constraint ? value != null && value !== '' : true;
|
|
325
|
+
return { valid, value };
|
|
326
|
+
},
|
|
327
|
+
/**
|
|
328
|
+
* Implementation of enum constraint
|
|
329
|
+
* @param constraint `enum` property of the form object
|
|
330
|
+
* @param value value of the form object
|
|
331
|
+
* @return {@link ValidationResult | validation result}
|
|
332
|
+
*/
|
|
333
|
+
enum: (constraint, value) => {
|
|
334
|
+
return {
|
|
335
|
+
valid: constraint.indexOf(value) > -1,
|
|
336
|
+
value
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
};
|