@rjsf/utils 5.11.2 → 5.12.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/dist/index.js +2544 -5
- package/dist/index.js.map +7 -0
- package/dist/utils.esm.js +1228 -2113
- package/dist/utils.esm.js.map +7 -1
- package/dist/utils.umd.js +2414 -0
- package/lib/ErrorSchemaBuilder.d.ts +60 -0
- package/lib/ErrorSchemaBuilder.js +103 -0
- package/lib/ErrorSchemaBuilder.js.map +1 -0
- package/lib/allowAdditionalItems.d.ts +8 -0
- package/lib/allowAdditionalItems.js +14 -0
- package/lib/allowAdditionalItems.js.map +1 -0
- package/lib/asNumber.d.ts +10 -0
- package/lib/asNumber.js +36 -0
- package/lib/asNumber.js.map +1 -0
- package/lib/canExpand.d.ts +11 -0
- package/lib/canExpand.js +26 -0
- package/lib/canExpand.js.map +1 -0
- package/lib/constants.d.ts +31 -0
- package/lib/constants.js +32 -0
- package/lib/constants.js.map +1 -0
- package/lib/createErrorHandler.d.ts +7 -0
- package/lib/createErrorHandler.js +31 -0
- package/lib/createErrorHandler.js.map +1 -0
- package/lib/createSchemaUtils.d.ts +10 -0
- package/lib/createSchemaUtils.js +207 -0
- package/lib/createSchemaUtils.js.map +1 -0
- package/lib/dataURItoBlob.d.ts +16 -0
- package/lib/dataURItoBlob.js +43 -0
- package/lib/dataURItoBlob.js.map +1 -0
- package/lib/deepEquals.d.ts +8 -0
- package/lib/deepEquals.js +19 -0
- package/lib/deepEquals.js.map +1 -0
- package/lib/englishStringTranslator.d.ts +10 -0
- package/lib/englishStringTranslator.js +13 -0
- package/lib/englishStringTranslator.js.map +1 -0
- package/lib/enumOptionsDeselectValue.d.ts +14 -0
- package/lib/enumOptionsDeselectValue.js +22 -0
- package/lib/enumOptionsDeselectValue.js.map +1 -0
- package/lib/enumOptionsIndexForValue.d.ts +13 -0
- package/lib/enumOptionsIndexForValue.js +22 -0
- package/lib/enumOptionsIndexForValue.js.map +1 -0
- package/lib/enumOptionsIsSelected.d.ts +8 -0
- package/lib/enumOptionsIsSelected.js +14 -0
- package/lib/enumOptionsIsSelected.js.map +1 -0
- package/lib/enumOptionsSelectValue.d.ts +10 -0
- package/lib/enumOptionsSelectValue.js +23 -0
- package/lib/enumOptionsSelectValue.js.map +1 -0
- package/lib/enumOptionsValueForIndex.d.ts +13 -0
- package/lib/enumOptionsValueForIndex.js +21 -0
- package/lib/enumOptionsValueForIndex.js.map +1 -0
- package/lib/enums.d.ts +72 -0
- package/lib/enums.js +76 -0
- package/lib/enums.js.map +1 -0
- package/lib/findSchemaDefinition.d.ts +20 -0
- package/lib/findSchemaDefinition.js +49 -0
- package/lib/findSchemaDefinition.js.map +1 -0
- package/lib/getDiscriminatorFieldFromSchema.d.ts +8 -0
- package/lib/getDiscriminatorFieldFromSchema.js +20 -0
- package/lib/getDiscriminatorFieldFromSchema.js.map +1 -0
- package/lib/getInputProps.d.ts +10 -0
- package/lib/getInputProps.js +41 -0
- package/lib/getInputProps.js.map +1 -0
- package/lib/getSchemaType.d.ts +13 -0
- package/lib/getSchemaType.js +29 -0
- package/lib/getSchemaType.js.map +1 -0
- package/lib/getSubmitButtonOptions.d.ts +10 -0
- package/lib/getSubmitButtonOptions.js +25 -0
- package/lib/getSubmitButtonOptions.js.map +1 -0
- package/lib/getTemplate.d.ts +10 -0
- package/lib/getTemplate.js +19 -0
- package/lib/getTemplate.js.map +1 -0
- package/lib/getUiOptions.d.ts +9 -0
- package/lib/getUiOptions.js +25 -0
- package/lib/getUiOptions.js.map +1 -0
- package/lib/getWidget.d.ts +13 -0
- package/lib/getWidget.js +118 -0
- package/lib/getWidget.js.map +1 -0
- package/lib/guessType.d.ts +7 -0
- package/lib/guessType.js +29 -0
- package/lib/guessType.js.map +1 -0
- package/lib/hasWidget.d.ts +10 -0
- package/lib/hasWidget.js +23 -0
- package/lib/hasWidget.js.map +1 -0
- package/lib/hashForSchema.d.ts +8 -0
- package/lib/hashForSchema.js +29 -0
- package/lib/hashForSchema.js.map +1 -0
- package/lib/idGenerators.d.ts +47 -0
- package/lib/idGenerators.js +73 -0
- package/lib/idGenerators.js.map +1 -0
- package/lib/index.d.ts +57 -0
- package/lib/index.js +58 -0
- package/lib/index.js.map +1 -0
- package/lib/isConstant.d.ts +8 -0
- package/lib/isConstant.js +11 -0
- package/lib/isConstant.js.map +1 -0
- package/lib/isCustomWidget.d.ts +7 -0
- package/lib/isCustomWidget.js +13 -0
- package/lib/isCustomWidget.js.map +1 -0
- package/lib/isFixedItems.d.ts +8 -0
- package/lib/isFixedItems.js +11 -0
- package/lib/isFixedItems.js.map +1 -0
- package/lib/isObject.d.ts +7 -0
- package/lib/isObject.js +16 -0
- package/lib/isObject.js.map +1 -0
- package/lib/labelValue.d.ts +13 -0
- package/lib/labelValue.js +4 -0
- package/lib/labelValue.js.map +1 -0
- package/lib/localToUTC.d.ts +6 -0
- package/lib/localToUTC.js +9 -0
- package/lib/localToUTC.js.map +1 -0
- package/lib/mergeDefaultsWithFormData.d.ts +17 -0
- package/lib/mergeDefaultsWithFormData.js +43 -0
- package/lib/mergeDefaultsWithFormData.js.map +1 -0
- package/lib/mergeObjects.d.ts +11 -0
- package/lib/mergeObjects.js +35 -0
- package/lib/mergeObjects.js.map +1 -0
- package/lib/mergeSchemas.d.ts +10 -0
- package/lib/mergeSchemas.js +35 -0
- package/lib/mergeSchemas.js.map +1 -0
- package/lib/optionsList.d.ts +10 -0
- package/lib/optionsList.js +36 -0
- package/lib/optionsList.js.map +1 -0
- package/lib/orderProperties.d.ts +11 -0
- package/lib/orderProperties.js +38 -0
- package/lib/orderProperties.js.map +1 -0
- package/lib/pad.d.ts +7 -0
- package/lib/pad.js +14 -0
- package/lib/pad.js.map +1 -0
- package/lib/parseDateString.d.ts +9 -0
- package/lib/parseDateString.js +32 -0
- package/lib/parseDateString.js.map +1 -0
- package/lib/parser/ParserValidator.d.ts +70 -0
- package/lib/parser/ParserValidator.js +93 -0
- package/lib/parser/ParserValidator.js.map +1 -0
- package/lib/parser/index.d.ts +4 -0
- package/lib/parser/index.js +3 -0
- package/lib/parser/index.js.map +1 -0
- package/lib/parser/schemaParser.d.ts +9 -0
- package/lib/parser/schemaParser.js +48 -0
- package/lib/parser/schemaParser.js.map +1 -0
- package/lib/rangeSpec.d.ts +9 -0
- package/lib/rangeSpec.js +20 -0
- package/lib/rangeSpec.js.map +1 -0
- package/lib/replaceStringParameters.d.ts +9 -0
- package/lib/replaceStringParameters.js +23 -0
- package/lib/replaceStringParameters.js.map +1 -0
- package/lib/schema/getClosestMatchingOption.d.ts +49 -0
- package/lib/schema/getClosestMatchingOption.js +154 -0
- package/lib/schema/getClosestMatchingOption.js.map +1 -0
- package/lib/schema/getDefaultFormState.d.ts +66 -0
- package/lib/schema/getDefaultFormState.js +351 -0
- package/lib/schema/getDefaultFormState.js.map +1 -0
- package/lib/schema/getDisplayLabel.d.ts +12 -0
- package/lib/schema/getDisplayLabel.js +39 -0
- package/lib/schema/getDisplayLabel.js.map +1 -0
- package/lib/schema/getFirstMatchingOption.d.ts +13 -0
- package/lib/schema/getFirstMatchingOption.js +16 -0
- package/lib/schema/getFirstMatchingOption.js.map +1 -0
- package/lib/schema/getMatchingOption.d.ts +14 -0
- package/lib/schema/getMatchingOption.js +80 -0
- package/lib/schema/getMatchingOption.js.map +1 -0
- package/lib/schema/index.d.ts +14 -0
- package/lib/schema/index.js +15 -0
- package/lib/schema/index.js.map +1 -0
- package/lib/schema/isFilesArray.d.ts +10 -0
- package/lib/schema/isFilesArray.js +21 -0
- package/lib/schema/isFilesArray.js.map +1 -0
- package/lib/schema/isMultiSelect.d.ts +9 -0
- package/lib/schema/isMultiSelect.js +15 -0
- package/lib/schema/isMultiSelect.js.map +1 -0
- package/lib/schema/isSelect.d.ts +9 -0
- package/lib/schema/isSelect.js +21 -0
- package/lib/schema/isSelect.js.map +1 -0
- package/lib/schema/mergeValidationData.d.ts +14 -0
- package/lib/schema/mergeValidationData.js +28 -0
- package/lib/schema/mergeValidationData.js.map +1 -0
- package/lib/schema/retrieveSchema.d.ts +170 -0
- package/lib/schema/retrieveSchema.js +437 -0
- package/lib/schema/retrieveSchema.js.map +1 -0
- package/lib/schema/sanitizeDataForNewSchema.d.ts +49 -0
- package/lib/schema/sanitizeDataForNewSchema.js +173 -0
- package/lib/schema/sanitizeDataForNewSchema.js.map +1 -0
- package/lib/schema/toIdSchema.d.ts +13 -0
- package/lib/schema/toIdSchema.js +59 -0
- package/lib/schema/toIdSchema.js.map +1 -0
- package/lib/schema/toPathSchema.d.ts +11 -0
- package/lib/schema/toPathSchema.js +68 -0
- package/lib/schema/toPathSchema.js.map +1 -0
- package/lib/schemaRequiresTrueValue.d.ts +11 -0
- package/lib/schemaRequiresTrueValue.js +34 -0
- package/lib/schemaRequiresTrueValue.js.map +1 -0
- package/lib/shouldRender.d.ts +10 -0
- package/lib/shouldRender.js +14 -0
- package/lib/shouldRender.js.map +1 -0
- package/lib/toConstant.d.ts +9 -0
- package/lib/toConstant.js +18 -0
- package/lib/toConstant.js.map +1 -0
- package/lib/toDateString.d.ts +9 -0
- package/lib/toDateString.js +14 -0
- package/lib/toDateString.js.map +1 -0
- package/lib/toErrorList.d.ts +8 -0
- package/lib/toErrorList.js +34 -0
- package/lib/toErrorList.js.map +1 -0
- package/lib/toErrorSchema.d.ts +21 -0
- package/lib/toErrorSchema.js +41 -0
- package/lib/toErrorSchema.js.map +1 -0
- package/lib/types.d.ts +982 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/lib/unwrapErrorHandler.d.ts +7 -0
- package/lib/unwrapErrorHandler.js +21 -0
- package/lib/unwrapErrorHandler.js.map +1 -0
- package/lib/utcToLocal.d.ts +6 -0
- package/lib/utcToLocal.js +26 -0
- package/lib/utcToLocal.js.map +1 -0
- package/lib/validationDataMerge.d.ts +11 -0
- package/lib/validationDataMerge.js +26 -0
- package/lib/validationDataMerge.js.map +1 -0
- package/lib/withIdRefPrefix.d.ts +8 -0
- package/lib/withIdRefPrefix.js +47 -0
- package/lib/withIdRefPrefix.js.map +1 -0
- package/package.json +20 -13
- package/src/ErrorSchemaBuilder.ts +112 -0
- package/src/allowAdditionalItems.ts +15 -0
- package/src/asNumber.ts +38 -0
- package/src/canExpand.ts +31 -0
- package/src/constants.ts +31 -0
- package/src/createErrorHandler.ts +33 -0
- package/src/createSchemaUtils.ts +298 -0
- package/src/dataURItoBlob.ts +42 -0
- package/src/deepEquals.ts +19 -0
- package/src/englishStringTranslator.ts +14 -0
- package/src/enumOptionsDeselectValue.ts +28 -0
- package/src/enumOptionsIndexForValue.ts +27 -0
- package/src/enumOptionsIsSelected.ts +19 -0
- package/src/enumOptionsSelectValue.ts +28 -0
- package/src/enumOptionsValueForIndex.ts +26 -0
- package/src/enums.ts +74 -0
- package/src/findSchemaDefinition.ts +54 -0
- package/src/getDiscriminatorFieldFromSchema.ts +21 -0
- package/src/getInputProps.ts +55 -0
- package/src/getSchemaType.ts +37 -0
- package/src/getSubmitButtonOptions.ts +32 -0
- package/src/getTemplate.ts +26 -0
- package/src/getUiOptions.ts +32 -0
- package/src/getWidget.tsx +133 -0
- package/src/guessType.ts +28 -0
- package/src/hasWidget.ts +27 -0
- package/src/hashForSchema.ts +31 -0
- package/src/idGenerators.ts +81 -0
- package/src/index.ts +118 -0
- package/src/isConstant.ts +12 -0
- package/src/isCustomWidget.ts +19 -0
- package/src/isFixedItems.ts +12 -0
- package/src/isObject.ts +15 -0
- package/src/labelValue.ts +16 -0
- package/src/localToUTC.ts +8 -0
- package/src/mergeDefaultsWithFormData.ts +53 -0
- package/src/mergeObjects.ts +39 -0
- package/src/mergeSchemas.ts +38 -0
- package/src/optionsList.ts +41 -0
- package/src/orderProperties.ts +44 -0
- package/src/pad.ts +13 -0
- package/src/parseDateString.ts +33 -0
- package/src/parser/ParserValidator.ts +132 -0
- package/src/parser/index.ts +6 -0
- package/src/parser/schemaParser.ts +60 -0
- package/src/rangeSpec.ts +22 -0
- package/src/replaceStringParameters.ts +22 -0
- package/src/schema/getClosestMatchingOption.ts +191 -0
- package/src/schema/getDefaultFormState.ts +447 -0
- package/src/schema/getDisplayLabel.ts +59 -0
- package/src/schema/getFirstMatchingOption.ts +27 -0
- package/src/schema/getMatchingOption.ts +95 -0
- package/src/schema/index.ts +29 -0
- package/src/schema/isFilesArray.ts +27 -0
- package/src/schema/isMultiSelect.ts +21 -0
- package/src/schema/isSelect.ts +26 -0
- package/src/schema/mergeValidationData.ts +38 -0
- package/src/schema/retrieveSchema.ts +614 -0
- package/src/schema/sanitizeDataForNewSchema.ts +197 -0
- package/src/schema/toIdSchema.ts +105 -0
- package/src/schema/toPathSchema.ts +121 -0
- package/src/schemaRequiresTrueValue.ts +40 -0
- package/src/shouldRender.ts +16 -0
- package/src/toConstant.ts +19 -0
- package/src/toDateString.ts +15 -0
- package/src/toErrorList.ts +41 -0
- package/src/toErrorSchema.ts +43 -0
- package/src/types.ts +1139 -0
- package/src/unwrapErrorHandler.ts +25 -0
- package/src/utcToLocal.ts +30 -0
- package/src/validationDataMerge.ts +31 -0
- package/src/withIdRefPrefix.ts +49 -0
- package/dist/index.d.ts +0 -1911
- package/dist/utils.cjs.development.js +0 -3522
- package/dist/utils.cjs.development.js.map +0 -1
- package/dist/utils.cjs.production.min.js +0 -2
- package/dist/utils.cjs.production.min.js.map +0 -1
- package/dist/utils.umd.development.js +0 -3504
- package/dist/utils.umd.development.js.map +0 -1
- package/dist/utils.umd.production.min.js +0 -2
- package/dist/utils.umd.production.min.js.map +0 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
|
|
3
|
+
/** Helper function that will return the value to use for a widget `label` based on `hideLabel`. The `fallback` is used
|
|
4
|
+
* as the return value from the function when `hideLabel` is true. Due to the implementation of theme components, it
|
|
5
|
+
* may be necessary to return something other than `undefined` to cause the theme component to not render a label. Some
|
|
6
|
+
* themes require may `false` and others may require an empty string.
|
|
7
|
+
*
|
|
8
|
+
* @param [label] - The label string or component to render when not hidden
|
|
9
|
+
* @param [hideLabel] - Flag, if true, will cause the label to be hidden
|
|
10
|
+
* @param [fallback] - One of 3 values, `undefined` (the default), `false` or an empty string
|
|
11
|
+
* @returns - `fallback` if `hideLabel` is true, otherwise `label`
|
|
12
|
+
*/
|
|
13
|
+
export function labelValue(label?: string | ReactElement, hideLabel?: boolean, fallback?: ''): undefined | string;
|
|
14
|
+
export default function labelValue(label?: string | ReactElement, hideLabel?: boolean, fallback?: false | '') {
|
|
15
|
+
return hideLabel ? fallback : label;
|
|
16
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Converts a local Date string into a UTC date string
|
|
2
|
+
*
|
|
3
|
+
* @param dateString - The string representation of a date as accepted by the `Date()` constructor
|
|
4
|
+
* @returns - A UTC date string if `dateString` is truthy, otherwise undefined
|
|
5
|
+
*/
|
|
6
|
+
export default function localToUTC(dateString: string) {
|
|
7
|
+
return dateString ? new Date(dateString).toJSON() : undefined;
|
|
8
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
|
|
3
|
+
import isObject from './isObject';
|
|
4
|
+
import { GenericObjectType } from '../src';
|
|
5
|
+
|
|
6
|
+
/** Merges the `defaults` object of type `T` into the `formData` of type `T`
|
|
7
|
+
*
|
|
8
|
+
* When merging defaults and form data, we want to merge in this specific way:
|
|
9
|
+
* - objects are deeply merged
|
|
10
|
+
* - arrays are merged in such a way that:
|
|
11
|
+
* - when the array is set in form data, only array entries set in form data
|
|
12
|
+
* are deeply merged; additional entries from the defaults are ignored unless `mergeExtraArrayDefaults` is true, in
|
|
13
|
+
* which case the extras are appended onto the end of the form data
|
|
14
|
+
* - when the array is not set in form data, the default is copied over
|
|
15
|
+
* - scalars are overwritten/set by form data
|
|
16
|
+
*
|
|
17
|
+
* @param [defaults] - The defaults to merge
|
|
18
|
+
* @param [formData] - The form data into which the defaults will be merged
|
|
19
|
+
* @param [mergeExtraArrayDefaults=false] - If true, any additional default array entries are appended onto the formData
|
|
20
|
+
* @returns - The resulting merged form data with defaults
|
|
21
|
+
*/
|
|
22
|
+
export default function mergeDefaultsWithFormData<T = any>(
|
|
23
|
+
defaults?: T,
|
|
24
|
+
formData?: T,
|
|
25
|
+
mergeExtraArrayDefaults = false
|
|
26
|
+
): T | undefined {
|
|
27
|
+
if (Array.isArray(formData)) {
|
|
28
|
+
const defaultsArray = Array.isArray(defaults) ? defaults : [];
|
|
29
|
+
const mapped = formData.map((value, idx) => {
|
|
30
|
+
if (defaultsArray[idx]) {
|
|
31
|
+
return mergeDefaultsWithFormData<any>(defaultsArray[idx], value, mergeExtraArrayDefaults);
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
});
|
|
35
|
+
// Merge any extra defaults when mergeExtraArrayDefaults is true
|
|
36
|
+
if (mergeExtraArrayDefaults && mapped.length < defaultsArray.length) {
|
|
37
|
+
mapped.push(...defaultsArray.slice(mapped.length));
|
|
38
|
+
}
|
|
39
|
+
return mapped as unknown as T;
|
|
40
|
+
}
|
|
41
|
+
if (isObject(formData)) {
|
|
42
|
+
const acc: { [key in keyof T]: any } = Object.assign({}, defaults); // Prevent mutation of source object.
|
|
43
|
+
return Object.keys(formData as GenericObjectType).reduce((acc, key) => {
|
|
44
|
+
acc[key as keyof T] = mergeDefaultsWithFormData<T>(
|
|
45
|
+
defaults ? get(defaults, key) : {},
|
|
46
|
+
get(formData, key),
|
|
47
|
+
mergeExtraArrayDefaults
|
|
48
|
+
);
|
|
49
|
+
return acc;
|
|
50
|
+
}, acc);
|
|
51
|
+
}
|
|
52
|
+
return formData;
|
|
53
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import isObject from './isObject';
|
|
2
|
+
import { GenericObjectType } from './types';
|
|
3
|
+
|
|
4
|
+
/** Recursively merge deeply nested objects.
|
|
5
|
+
*
|
|
6
|
+
* @param obj1 - The first object to merge
|
|
7
|
+
* @param obj2 - The second object to merge
|
|
8
|
+
* @param [concatArrays=false] - Optional flag that, when true, will cause arrays to be concatenated. Use
|
|
9
|
+
* "preventDuplicates" to merge arrays in a manner that prevents any duplicate entries from being merged.
|
|
10
|
+
* NOTE: Uses shallow comparison for the duplicate checking.
|
|
11
|
+
* @returns - A new object that is the merge of the two given objects
|
|
12
|
+
*/
|
|
13
|
+
export default function mergeObjects(
|
|
14
|
+
obj1: GenericObjectType,
|
|
15
|
+
obj2: GenericObjectType,
|
|
16
|
+
concatArrays: boolean | 'preventDuplicates' = false
|
|
17
|
+
) {
|
|
18
|
+
return Object.keys(obj2).reduce((acc, key) => {
|
|
19
|
+
const left = obj1 ? obj1[key] : {},
|
|
20
|
+
right = obj2[key];
|
|
21
|
+
if (obj1 && key in obj1 && isObject(right)) {
|
|
22
|
+
acc[key] = mergeObjects(left, right, concatArrays);
|
|
23
|
+
} else if (concatArrays && Array.isArray(left) && Array.isArray(right)) {
|
|
24
|
+
let toMerge = right;
|
|
25
|
+
if (concatArrays === 'preventDuplicates') {
|
|
26
|
+
toMerge = right.reduce((result, value) => {
|
|
27
|
+
if (!left.includes(value)) {
|
|
28
|
+
result.push(value);
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}, []);
|
|
32
|
+
}
|
|
33
|
+
acc[key] = left.concat(toMerge);
|
|
34
|
+
} else {
|
|
35
|
+
acc[key] = right;
|
|
36
|
+
}
|
|
37
|
+
return acc;
|
|
38
|
+
}, Object.assign({}, obj1)); // Prevent mutation of source object.
|
|
39
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import union from 'lodash/union';
|
|
2
|
+
|
|
3
|
+
import { REQUIRED_KEY } from './constants';
|
|
4
|
+
import getSchemaType from './getSchemaType';
|
|
5
|
+
import isObject from './isObject';
|
|
6
|
+
import { GenericObjectType } from './types';
|
|
7
|
+
|
|
8
|
+
/** Recursively merge deeply nested schemas. The difference between `mergeSchemas` and `mergeObjects` is that
|
|
9
|
+
* `mergeSchemas` only concats arrays for values under the 'required' keyword, and when it does, it doesn't include
|
|
10
|
+
* duplicate values.
|
|
11
|
+
*
|
|
12
|
+
* @param obj1 - The first schema object to merge
|
|
13
|
+
* @param obj2 - The second schema object to merge
|
|
14
|
+
* @returns - The merged schema object
|
|
15
|
+
*/
|
|
16
|
+
export default function mergeSchemas(obj1: GenericObjectType, obj2: GenericObjectType) {
|
|
17
|
+
const acc = Object.assign({}, obj1); // Prevent mutation of source object.
|
|
18
|
+
return Object.keys(obj2).reduce((acc, key) => {
|
|
19
|
+
const left = obj1 ? obj1[key] : {},
|
|
20
|
+
right = obj2[key];
|
|
21
|
+
if (obj1 && key in obj1 && isObject(right)) {
|
|
22
|
+
acc[key] = mergeSchemas(left, right);
|
|
23
|
+
} else if (
|
|
24
|
+
obj1 &&
|
|
25
|
+
obj2 &&
|
|
26
|
+
(getSchemaType(obj1) === 'object' || getSchemaType(obj2) === 'object') &&
|
|
27
|
+
key === REQUIRED_KEY &&
|
|
28
|
+
Array.isArray(left) &&
|
|
29
|
+
Array.isArray(right)
|
|
30
|
+
) {
|
|
31
|
+
// Don't include duplicate values when merging 'required' fields.
|
|
32
|
+
acc[key] = union(left, right);
|
|
33
|
+
} else {
|
|
34
|
+
acc[key] = right;
|
|
35
|
+
}
|
|
36
|
+
return acc;
|
|
37
|
+
}, acc);
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import toConstant from './toConstant';
|
|
2
|
+
import { RJSFSchema, EnumOptionsType, StrictRJSFSchema } from './types';
|
|
3
|
+
|
|
4
|
+
/** Gets the list of options from the schema. If the schema has an enum list, then those enum values are returned. The
|
|
5
|
+
* labels for the options will be extracted from the non-standard, RJSF-deprecated `enumNames` if it exists, otherwise
|
|
6
|
+
* the label will be the same as the `value`. If the schema has a `oneOf` or `anyOf`, then the value is the list of
|
|
7
|
+
* `const` values from the schema and the label is either the `schema.title` or the value.
|
|
8
|
+
*
|
|
9
|
+
* @param schema - The schema from which to extract the options list
|
|
10
|
+
* @returns - The list of options from the schema
|
|
11
|
+
*/
|
|
12
|
+
export default function optionsList<S extends StrictRJSFSchema = RJSFSchema>(
|
|
13
|
+
schema: S
|
|
14
|
+
): EnumOptionsType<S>[] | undefined {
|
|
15
|
+
// enumNames was deprecated in v5 and is intentionally omitted from the RJSFSchema type.
|
|
16
|
+
// Cast the type to include enumNames so the feature still works.
|
|
17
|
+
const schemaWithEnumNames = schema as S & { enumNames?: string[] };
|
|
18
|
+
if (schemaWithEnumNames.enumNames && process.env.NODE_ENV !== 'production') {
|
|
19
|
+
console.warn('The enumNames property is deprecated and may be removed in a future major release.');
|
|
20
|
+
}
|
|
21
|
+
if (schema.enum) {
|
|
22
|
+
return schema.enum.map((value, i) => {
|
|
23
|
+
const label = (schemaWithEnumNames.enumNames && schemaWithEnumNames.enumNames[i]) || String(value);
|
|
24
|
+
return { label, value };
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const altSchemas = schema.oneOf || schema.anyOf;
|
|
28
|
+
return (
|
|
29
|
+
altSchemas &&
|
|
30
|
+
altSchemas.map((aSchemaDef) => {
|
|
31
|
+
const aSchema = aSchemaDef as S;
|
|
32
|
+
const value = toConstant(aSchema);
|
|
33
|
+
const label = aSchema.title || String(value);
|
|
34
|
+
return {
|
|
35
|
+
schema: aSchema,
|
|
36
|
+
label,
|
|
37
|
+
value,
|
|
38
|
+
};
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { GenericObjectType } from './types';
|
|
2
|
+
|
|
3
|
+
/** Given a list of `properties` and an `order` list, returns a list that contains the `properties` ordered correctly.
|
|
4
|
+
* If `order` is not an array, then the untouched `properties` list is returned. Otherwise `properties` is ordered per
|
|
5
|
+
* the `order` list. If `order` contains a '*' then any `properties` that are not mentioned explicity in `order` will be
|
|
6
|
+
* places in the location of the `*`.
|
|
7
|
+
*
|
|
8
|
+
* @param properties - The list of property keys to be ordered
|
|
9
|
+
* @param order - An array of property keys to be ordered first, with an optional '*' property
|
|
10
|
+
* @returns - A list with the `properties` ordered
|
|
11
|
+
* @throws - Error when the properties cannot be ordered correctly
|
|
12
|
+
*/
|
|
13
|
+
export default function orderProperties(properties: string[], order?: string[]): string[] {
|
|
14
|
+
if (!Array.isArray(order)) {
|
|
15
|
+
return properties;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const arrayToHash = (arr: string[]) =>
|
|
19
|
+
arr.reduce((prev: GenericObjectType, curr) => {
|
|
20
|
+
prev[curr] = true;
|
|
21
|
+
return prev;
|
|
22
|
+
}, {});
|
|
23
|
+
const errorPropList = (arr: string[]) =>
|
|
24
|
+
arr.length > 1 ? `properties '${arr.join("', '")}'` : `property '${arr[0]}'`;
|
|
25
|
+
const propertyHash = arrayToHash(properties);
|
|
26
|
+
const orderFiltered = order.filter((prop) => prop === '*' || propertyHash[prop]);
|
|
27
|
+
const orderHash = arrayToHash(orderFiltered);
|
|
28
|
+
|
|
29
|
+
const rest = properties.filter((prop: string) => !orderHash[prop]);
|
|
30
|
+
const restIndex = orderFiltered.indexOf('*');
|
|
31
|
+
if (restIndex === -1) {
|
|
32
|
+
if (rest.length) {
|
|
33
|
+
throw new Error(`uiSchema order list does not contain ${errorPropList(rest)}`);
|
|
34
|
+
}
|
|
35
|
+
return orderFiltered;
|
|
36
|
+
}
|
|
37
|
+
if (restIndex !== orderFiltered.lastIndexOf('*')) {
|
|
38
|
+
throw new Error('uiSchema order list contains more than one wildcard item');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const complete = [...orderFiltered];
|
|
42
|
+
complete.splice(restIndex, 1, ...rest);
|
|
43
|
+
return complete;
|
|
44
|
+
}
|
package/src/pad.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Returns a string representation of the `num` that is padded with leading "0"s if necessary
|
|
2
|
+
*
|
|
3
|
+
* @param num - The number to pad
|
|
4
|
+
* @param width - The width of the string at which no lead padding is necessary
|
|
5
|
+
* @returns - The number converted to a string with leading zero padding if the number of digits is less than `width`
|
|
6
|
+
*/
|
|
7
|
+
export default function pad(num: number, width: number) {
|
|
8
|
+
let s = String(num);
|
|
9
|
+
while (s.length < width) {
|
|
10
|
+
s = '0' + s;
|
|
11
|
+
}
|
|
12
|
+
return s;
|
|
13
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DateObject } from './types';
|
|
2
|
+
|
|
3
|
+
/** Parses the `dateString` into a `DateObject`, including the time information when `includeTime` is true
|
|
4
|
+
*
|
|
5
|
+
* @param dateString - The date string to parse into a DateObject
|
|
6
|
+
* @param [includeTime=true] - Optional flag, if false, will not include the time data into the object
|
|
7
|
+
* @returns - The date string converted to a `DateObject`
|
|
8
|
+
* @throws - Error when the date cannot be parsed from the string
|
|
9
|
+
*/
|
|
10
|
+
export default function parseDateString(dateString?: string, includeTime = true): DateObject {
|
|
11
|
+
if (!dateString) {
|
|
12
|
+
return {
|
|
13
|
+
year: -1,
|
|
14
|
+
month: -1,
|
|
15
|
+
day: -1,
|
|
16
|
+
hour: includeTime ? -1 : 0,
|
|
17
|
+
minute: includeTime ? -1 : 0,
|
|
18
|
+
second: includeTime ? -1 : 0,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const date = new Date(dateString);
|
|
22
|
+
if (Number.isNaN(date.getTime())) {
|
|
23
|
+
throw new Error('Unable to parse date ' + dateString);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
year: date.getUTCFullYear(),
|
|
27
|
+
month: date.getUTCMonth() + 1, // oh you, javascript.
|
|
28
|
+
day: date.getUTCDate(),
|
|
29
|
+
hour: includeTime ? date.getUTCHours() : 0,
|
|
30
|
+
minute: includeTime ? date.getUTCMinutes() : 0,
|
|
31
|
+
second: includeTime ? date.getUTCSeconds() : 0,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
|
|
4
|
+
import { ID_KEY } from '../constants';
|
|
5
|
+
import hashForSchema from '../hashForSchema';
|
|
6
|
+
import {
|
|
7
|
+
CustomValidator,
|
|
8
|
+
ErrorSchema,
|
|
9
|
+
ErrorTransformer,
|
|
10
|
+
FormContextType,
|
|
11
|
+
RJSFSchema,
|
|
12
|
+
RJSFValidationError,
|
|
13
|
+
StrictRJSFSchema,
|
|
14
|
+
UiSchema,
|
|
15
|
+
ValidationData,
|
|
16
|
+
ValidatorType,
|
|
17
|
+
} from '../types';
|
|
18
|
+
|
|
19
|
+
/** The type of the map of schema hash to schema
|
|
20
|
+
*/
|
|
21
|
+
export type SchemaMap<S extends StrictRJSFSchema = RJSFSchema> = {
|
|
22
|
+
[hash: string]: S;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** An implementation of the `ValidatorType` interface that is designed for use in capturing schemas used by the
|
|
26
|
+
* `isValid()` function. The rest of the implementation of the interface throws errors when it is attempted to be used.
|
|
27
|
+
* An instance of the object allows the caller to capture the schemas used in calls to the `isValid()` function. These
|
|
28
|
+
* captured schema, along with the root schema used to construct the object are stored in the map of schemas keyed by
|
|
29
|
+
* the hashed value of the schema. NOTE: After hashing the schema, an $id with the hash value is added to the
|
|
30
|
+
* schema IF that schema doesn't already have an $id, prior to putting the schema into the map.
|
|
31
|
+
*/
|
|
32
|
+
export default class ParserValidator<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
|
|
33
|
+
implements ValidatorType<T, S, F>
|
|
34
|
+
{
|
|
35
|
+
/** The rootSchema provided during construction of the class */
|
|
36
|
+
readonly rootSchema: S;
|
|
37
|
+
|
|
38
|
+
/** The map of schemas encountered by the ParserValidator */
|
|
39
|
+
schemaMap: SchemaMap<S> = {};
|
|
40
|
+
|
|
41
|
+
/** Construct the ParserValidator for the given `rootSchema`. This `rootSchema` will be stashed in the `schemaMap`
|
|
42
|
+
* first.
|
|
43
|
+
*
|
|
44
|
+
* @param rootSchema - The root schema against which this validator will be executed
|
|
45
|
+
*/
|
|
46
|
+
constructor(rootSchema: S) {
|
|
47
|
+
this.rootSchema = rootSchema;
|
|
48
|
+
this.addSchema(rootSchema, hashForSchema<S>(rootSchema));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Adds the given `schema` to the `schemaMap` keyed by the `hash` or `ID_KEY` if present on the `schema`. If the
|
|
52
|
+
* schema does not have an `ID_KEY`, then the `hash` will be added as the `ID_KEY` to allow the schema to be
|
|
53
|
+
* associated with it's `hash` for future use (by a schema compiler).
|
|
54
|
+
*
|
|
55
|
+
* @param schema - The schema which is to be added to the map
|
|
56
|
+
* @param hash - The hash value at which to map the schema
|
|
57
|
+
*/
|
|
58
|
+
addSchema(schema: S, hash: string) {
|
|
59
|
+
const key = get(schema, ID_KEY, hash);
|
|
60
|
+
const identifiedSchema = { ...schema, [ID_KEY]: key };
|
|
61
|
+
const existing = this.schemaMap[key];
|
|
62
|
+
if (!existing) {
|
|
63
|
+
this.schemaMap[key] = identifiedSchema;
|
|
64
|
+
} else if (!isEqual(existing, identifiedSchema)) {
|
|
65
|
+
console.error('existing schema:', JSON.stringify(existing, null, 2));
|
|
66
|
+
console.error('new schema:', JSON.stringify(identifiedSchema, null, 2));
|
|
67
|
+
throw new Error(
|
|
68
|
+
`Two different schemas exist with the same key ${key}! What a bad coincidence. If possible, try adding an $id to one of the schemas`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Returns the current `schemaMap` to the caller
|
|
74
|
+
*/
|
|
75
|
+
getSchemaMap() {
|
|
76
|
+
return this.schemaMap;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Implements the `ValidatorType` `isValid()` method to capture the `schema` in the `schemaMap`. Throws an error when
|
|
80
|
+
* the `rootSchema` is not the same as the root schema provided during construction.
|
|
81
|
+
*
|
|
82
|
+
* @param schema - The schema to record in the `schemaMap`
|
|
83
|
+
* @param _formData - The formData parameter that is ignored
|
|
84
|
+
* @param rootSchema - The root schema associated with the schema
|
|
85
|
+
* @throws - Error when the given `rootSchema` differs from the root schema provided during construction
|
|
86
|
+
*/
|
|
87
|
+
isValid(schema: S, _formData: T, rootSchema: S): boolean {
|
|
88
|
+
if (!isEqual(rootSchema, this.rootSchema)) {
|
|
89
|
+
throw new Error('Unexpectedly calling isValid() with a rootSchema that differs from the construction rootSchema');
|
|
90
|
+
}
|
|
91
|
+
this.addSchema(schema, hashForSchema<S>(schema));
|
|
92
|
+
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Implements the `ValidatorType` `rawValidation()` method to throw an error since it is never supposed to be called
|
|
97
|
+
*
|
|
98
|
+
* @param _schema - The schema parameter that is ignored
|
|
99
|
+
* @param _formData - The formData parameter that is ignored
|
|
100
|
+
*/
|
|
101
|
+
rawValidation<Result = any>(_schema: S, _formData?: T): { errors?: Result[]; validationError?: Error } {
|
|
102
|
+
throw new Error('Unexpectedly calling the `rawValidation()` method during schema parsing');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Implements the `ValidatorType` `toErrorList()` method to throw an error since it is never supposed to be called
|
|
106
|
+
*
|
|
107
|
+
* @param _errorSchema - The error schema parameter that is ignored
|
|
108
|
+
* @param _fieldPath - The field path parameter that is ignored
|
|
109
|
+
*/
|
|
110
|
+
toErrorList(_errorSchema?: ErrorSchema<T>, _fieldPath?: string[]): RJSFValidationError[] {
|
|
111
|
+
throw new Error('Unexpectedly calling the `toErrorList()` method during schema parsing');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Implements the `ValidatorType` `validateFormData()` method to throw an error since it is never supposed to be
|
|
115
|
+
* called
|
|
116
|
+
*
|
|
117
|
+
* @param _formData - The formData parameter that is ignored
|
|
118
|
+
* @param _schema - The schema parameter that is ignored
|
|
119
|
+
* @param _customValidate - The customValidate parameter that is ignored
|
|
120
|
+
* @param _transformErrors - The transformErrors parameter that is ignored
|
|
121
|
+
* @param _uiSchema - The uiSchema parameter that is ignored
|
|
122
|
+
*/
|
|
123
|
+
validateFormData(
|
|
124
|
+
_formData: T,
|
|
125
|
+
_schema: S,
|
|
126
|
+
_customValidate?: CustomValidator<T, S, F>,
|
|
127
|
+
_transformErrors?: ErrorTransformer<T, S, F>,
|
|
128
|
+
_uiSchema?: UiSchema<T, S, F>
|
|
129
|
+
): ValidationData<T> {
|
|
130
|
+
throw new Error('Unexpectedly calling the `validateFormData()` method during schema parsing');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import forEach from 'lodash/forEach';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
|
|
4
|
+
import { FormContextType, RJSFSchema, StrictRJSFSchema } from '../types';
|
|
5
|
+
import { PROPERTIES_KEY, ITEMS_KEY } from '../constants';
|
|
6
|
+
import ParserValidator, { SchemaMap } from './ParserValidator';
|
|
7
|
+
import { retrieveSchemaInternal, resolveAnyOrOneOfSchemas } from '../schema/retrieveSchema';
|
|
8
|
+
|
|
9
|
+
/** Recursive function used to parse the given `schema` belonging to the `rootSchema`. The `validator` is used to
|
|
10
|
+
* capture the sub-schemas that the `isValid()` function is called with. For each schema returned by the
|
|
11
|
+
* `retrieveSchemaInternal()`, the `resolveAnyOrOneOfSchemas()` function is called. For each of the schemas returned
|
|
12
|
+
* from THAT call have `properties`, then each of the sub-schema property objects are then recursively parsed.
|
|
13
|
+
*
|
|
14
|
+
* @param validator - The `ParserValidator` implementation used to capture `isValid()` calls during parsing
|
|
15
|
+
* @param recurseList - The list of schemas returned from the `retrieveSchemaInternal`, preventing infinite recursion
|
|
16
|
+
* @param rootSchema - The root schema from which the schema parsing began
|
|
17
|
+
* @param schema - The current schema element being parsed
|
|
18
|
+
*/
|
|
19
|
+
function parseSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
20
|
+
validator: ParserValidator<T, S, F>,
|
|
21
|
+
recurseList: S[],
|
|
22
|
+
rootSchema: S,
|
|
23
|
+
schema: S
|
|
24
|
+
) {
|
|
25
|
+
const schemas = retrieveSchemaInternal<T, S, F>(validator, schema, rootSchema, undefined, true);
|
|
26
|
+
schemas.forEach((schema) => {
|
|
27
|
+
const sameSchemaIndex = recurseList.findIndex((item) => isEqual(item, schema));
|
|
28
|
+
if (sameSchemaIndex === -1) {
|
|
29
|
+
recurseList.push(schema);
|
|
30
|
+
const allOptions = resolveAnyOrOneOfSchemas<T, S, F>(validator, schema, rootSchema, true);
|
|
31
|
+
allOptions.forEach((s) => {
|
|
32
|
+
if (PROPERTIES_KEY in s && s[PROPERTIES_KEY]) {
|
|
33
|
+
forEach(schema[PROPERTIES_KEY], (value) => {
|
|
34
|
+
parseSchema<T, S, F>(validator, recurseList, rootSchema, value as S);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
if (ITEMS_KEY in schema && !Array.isArray(schema.items) && typeof schema.items !== 'boolean') {
|
|
39
|
+
parseSchema<T, S, F>(validator, recurseList, rootSchema, schema.items as S);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Parses the given `rootSchema` to extract out all the sub-schemas that maybe contained within it. Returns a map of
|
|
46
|
+
* the hash of the schema to schema/sub-schema.
|
|
47
|
+
*
|
|
48
|
+
* @param rootSchema - The root schema to parse for sub-schemas used by `isValid()` calls
|
|
49
|
+
* @returns - The `SchemaMap` of all schemas that were parsed
|
|
50
|
+
*/
|
|
51
|
+
export default function schemaParser<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
52
|
+
rootSchema: S
|
|
53
|
+
): SchemaMap<S> {
|
|
54
|
+
const validator = new ParserValidator<T, S, F>(rootSchema);
|
|
55
|
+
const recurseList: S[] = [];
|
|
56
|
+
|
|
57
|
+
parseSchema(validator, recurseList, rootSchema, rootSchema);
|
|
58
|
+
|
|
59
|
+
return validator.getSchemaMap();
|
|
60
|
+
}
|
package/src/rangeSpec.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RangeSpecType, StrictRJSFSchema } from './types';
|
|
2
|
+
import { RJSFSchema } from './types';
|
|
3
|
+
|
|
4
|
+
/** Extracts the range spec information `{ step?: number, min?: number, max?: number }` that can be spread onto an HTML
|
|
5
|
+
* input from the range analog in the schema `{ multipleOf?: number, minimum?: number, maximum?: number }`.
|
|
6
|
+
*
|
|
7
|
+
* @param schema - The schema from which to extract the range spec
|
|
8
|
+
* @returns - A range specification from the schema
|
|
9
|
+
*/
|
|
10
|
+
export default function rangeSpec<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {
|
|
11
|
+
const spec: RangeSpecType = {};
|
|
12
|
+
if (schema.multipleOf) {
|
|
13
|
+
spec.step = schema.multipleOf;
|
|
14
|
+
}
|
|
15
|
+
if (schema.minimum || schema.minimum === 0) {
|
|
16
|
+
spec.min = schema.minimum;
|
|
17
|
+
}
|
|
18
|
+
if (schema.maximum || schema.maximum === 0) {
|
|
19
|
+
spec.max = schema.maximum;
|
|
20
|
+
}
|
|
21
|
+
return spec;
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Potentially substitutes all replaceable parameters with the associated value(s) from the `params` if available. When
|
|
2
|
+
* a `params` array is provided, each value in the array is used to replace any of the replaceable parameters in the
|
|
3
|
+
* `inputString` using the `%1`, `%2`, etc. replacement specifiers.
|
|
4
|
+
*
|
|
5
|
+
* @param inputString - The string which will be potentially updated with replacement parameters
|
|
6
|
+
* @param params - The optional list of replaceable parameter values to substitute into the english string
|
|
7
|
+
* @returns - The updated string with any replacement specifiers replaced
|
|
8
|
+
*/
|
|
9
|
+
export default function replaceStringParameters(inputString: string, params?: string[]) {
|
|
10
|
+
let output = inputString;
|
|
11
|
+
if (Array.isArray(params)) {
|
|
12
|
+
const parts = output.split(/(%\d)/);
|
|
13
|
+
params.forEach((param, index) => {
|
|
14
|
+
const partIndex = parts.findIndex((part) => part === `%${index + 1}`);
|
|
15
|
+
if (partIndex >= 0) {
|
|
16
|
+
parts[partIndex] = param;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
output = parts.join('');
|
|
20
|
+
}
|
|
21
|
+
return output;
|
|
22
|
+
}
|