lucid-extension-sdk 0.0.360 → 0.0.362
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/core/pruners/pruners.js
CHANGED
|
@@ -64,7 +64,7 @@ function pruneObjectField() {
|
|
|
64
64
|
return (data, invalidFields, level = 0, key = undefined) => {
|
|
65
65
|
var _a;
|
|
66
66
|
// When this is called as a part of objectPruner, level will be atleast 1
|
|
67
|
-
if ((0, checks_1.isArray)(data) ||
|
|
67
|
+
if ((0, checks_1.isArray)(data) || level <= 0) {
|
|
68
68
|
return data;
|
|
69
69
|
}
|
|
70
70
|
const invalidFieldAtCurrentLevel = (_a = invalidFields === null || invalidFields === void 0 ? void 0 : invalidFields.get(level - 1)) === null || _a === void 0 ? void 0 : _a.filter(checks_1.isArray);
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { WithUndefinedAsOptional } from '../optionalkey';
|
|
2
|
+
/**
|
|
3
|
+
* ObjectAttributeType represents the possible keys for an Object.
|
|
4
|
+
* (equivalent to string | number | symbol.) */
|
|
5
|
+
type ObjectAttributeType = keyof any;
|
|
6
|
+
/**
|
|
7
|
+
* A generic type for a Validator that narrows FROM to TO.
|
|
8
|
+
*/
|
|
9
|
+
type Validator<TO extends FROM, FROM = unknown> = (unknownVariable: FROM) => unknownVariable is TO;
|
|
10
|
+
/**
|
|
11
|
+
* A record that maps each key in an object to its respective ValidatorWithOptionalPruner.
|
|
12
|
+
*/
|
|
13
|
+
type ObjectValidatorConfig = Record<ObjectAttributeType, ValidatorWithOptionalPruner<unknown> | Validator<unknown>>;
|
|
14
|
+
/**
|
|
15
|
+
* A generic type for a pruner function. It takes in any data and returns:
|
|
16
|
+
* - prunerResult: The pruned data (or possibly the same data if no pruning is needed) which also constains
|
|
17
|
+
* invalidFields: a map of invalid fields (represented by keys) to their original invalid values.
|
|
18
|
+
*/
|
|
19
|
+
type Pruner = (unprunedData: unknown) => PrunerResult;
|
|
20
|
+
/**
|
|
21
|
+
* The result object returned from a pruner function.
|
|
22
|
+
*/
|
|
23
|
+
export interface PrunerResult {
|
|
24
|
+
prunerResult: unknown;
|
|
25
|
+
invalidFields: Map<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Represents a validator and an optional pruner.
|
|
29
|
+
*
|
|
30
|
+
* - `validator` is the function used to validate the data.
|
|
31
|
+
* - `pruner` can optionally used to prune invalid data fields if validation fails.
|
|
32
|
+
*/
|
|
33
|
+
interface ValidatorWithOptionalPruner<TO = unknown> {
|
|
34
|
+
'validator': Validator<TO>;
|
|
35
|
+
'pruner'?: Pruner;
|
|
36
|
+
}
|
|
37
|
+
interface ValidatorWithPruner<TO = unknown> {
|
|
38
|
+
'validator': Validator<TO>;
|
|
39
|
+
'pruner': Pruner;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Helper type that extracts the "TO" type from a ValidatorWithOptionalPruner<T>.
|
|
43
|
+
*/
|
|
44
|
+
type ExtractValidatedTypeFromConfig<V> = V extends {
|
|
45
|
+
validator: Validator<infer U>;
|
|
46
|
+
} ? U : V extends Validator<infer U> ? U : never;
|
|
47
|
+
/**
|
|
48
|
+
* Converts an ObjectValidator into a validated TypeScript type by inferring each property's `TO` type from its `validator`.
|
|
49
|
+
* Note it also makes undefined properties optional.
|
|
50
|
+
*/
|
|
51
|
+
type ObjectValidatorToValidatedType<T extends ObjectValidatorConfig> = WithUndefinedAsOptional<{
|
|
52
|
+
[K in keyof T]: ExtractValidatedTypeFromConfig<T[K]>;
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Recursively applies a "prettifying" transformation to the inferred object type.
|
|
56
|
+
* - For functions, it leaves them as-is.
|
|
57
|
+
* - For objects, it recurses down into properties.
|
|
58
|
+
* - Otherwise, returns the type unchanged.
|
|
59
|
+
*/
|
|
60
|
+
type PrettifyDeep<T> = T extends (...args: any[]) => any ? T : T extends object ? {
|
|
61
|
+
[K in keyof T]: PrettifyDeep<T[K]>;
|
|
62
|
+
} : T;
|
|
63
|
+
/**
|
|
64
|
+
* Extracts the final type from @param ObjectValidatorConfig
|
|
65
|
+
*/
|
|
66
|
+
type PrettifiedObjectValidatorType<T extends ObjectValidatorConfig> = PrettifyDeep<ObjectValidatorToValidatedType<T>>;
|
|
67
|
+
export type ExtractValidatedTypeFromValidator<V extends Validator<unknown>> = V extends Validator<infer U> ? U : never;
|
|
68
|
+
/**
|
|
69
|
+
* Creates a validator and pruner for an object.
|
|
70
|
+
*
|
|
71
|
+
* - The validator will ensure that all properties pass their respective child validator.
|
|
72
|
+
* - The pruner will remove or transform invalid fields as configured by the child pruners.
|
|
73
|
+
*
|
|
74
|
+
* @param objectValidatorConfig A record mapping property keys to their validators (and optional pruners).
|
|
75
|
+
* @returns ValidatorWithPruner for the object.
|
|
76
|
+
*/
|
|
77
|
+
export declare function getObjectValidatorAndPruner<T extends ObjectValidatorConfig>(objectValidatorConfig: T): ValidatorWithPruner<PrettifiedObjectValidatorType<T>>;
|
|
78
|
+
/**
|
|
79
|
+
* Create a validator and pruner for an array of elements.
|
|
80
|
+
*
|
|
81
|
+
* - The validator ensures that each element in the array passes a common element validator.
|
|
82
|
+
* - The pruner removes or transforms invalid elements as configured by the element pruner.
|
|
83
|
+
*
|
|
84
|
+
* @param arrayElementConfig A single validator (and optionally a pruner) used for each element.
|
|
85
|
+
* @returns ValidatorWithPruner for the array.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getArrayValidatorAndPruner<ElementType>(arrayElementConfig: ValidatorWithOptionalPruner<ElementType> | Validator<ElementType>): ValidatorWithPruner<ElementType[]>;
|
|
88
|
+
/**
|
|
89
|
+
* Function used in objectFieldConfig and arrayElementConfig to speficy that invalid
|
|
90
|
+
* items must be pruned/marked as undefined.
|
|
91
|
+
* @param element The data that failed validation and needs pruning.
|
|
92
|
+
*/
|
|
93
|
+
export declare const pruneElement: (element: unknown) => PrunerResult;
|
|
94
|
+
/**
|
|
95
|
+
* Combines a "per-element pruner" for an array’s elements with an "entire array pruner."
|
|
96
|
+
*
|
|
97
|
+
* - If the incoming data is not an array, it applies the `wholeArrayPruner`.
|
|
98
|
+
* - If it is an array, it applies the `perElementPruner` to each element.
|
|
99
|
+
*
|
|
100
|
+
* This is useful when you have specialized logic for array-level pruning
|
|
101
|
+
* (e.g., removing the entire array if it fails some overarching condition)
|
|
102
|
+
* but still want to prune individual elements if possible.
|
|
103
|
+
*
|
|
104
|
+
* @param perElementPruner A pruner for each element in the array.
|
|
105
|
+
* @param wholeArrayPruner A pruner for the entire array.
|
|
106
|
+
* @returns A Pruner that handles both array-level and element-level pruning.
|
|
107
|
+
*/
|
|
108
|
+
export declare function liftArrayPruner(perElementPruner: Pruner, wholeArrayPruner: Pruner): Pruner;
|
|
109
|
+
/**
|
|
110
|
+
* Helper function to easily create a `ValidatorWithOptionalPruner`.
|
|
111
|
+
*
|
|
112
|
+
* @param validator The validation function to determine valid vs invalid data.
|
|
113
|
+
* @param pruner The optional pruner function to sanitize or remove invalid data.
|
|
114
|
+
* @returns An object containing both the validator and the (optional) pruner.
|
|
115
|
+
*/
|
|
116
|
+
export declare function getValidatorPrunerConfig<TO>(validator: Validator<TO>, pruner?: Pruner): ValidatorWithOptionalPruner<TO>;
|
|
117
|
+
export {};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getValidatorPrunerConfig = exports.liftArrayPruner = exports.pruneElement = exports.getArrayValidatorAndPruner = exports.getObjectValidatorAndPruner = void 0;
|
|
4
|
+
const checks_1 = require("../checks");
|
|
5
|
+
function getValidatorFromConfig(validatorConfig) {
|
|
6
|
+
if ('validator' in validatorConfig) {
|
|
7
|
+
return validatorConfig.validator;
|
|
8
|
+
}
|
|
9
|
+
return validatorConfig;
|
|
10
|
+
}
|
|
11
|
+
function getPrunerFromConfig(validatorConfig) {
|
|
12
|
+
if ('pruner' in validatorConfig) {
|
|
13
|
+
return validatorConfig.pruner;
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a validator and pruner for an object.
|
|
19
|
+
*
|
|
20
|
+
* - The validator will ensure that all properties pass their respective child validator.
|
|
21
|
+
* - The pruner will remove or transform invalid fields as configured by the child pruners.
|
|
22
|
+
*
|
|
23
|
+
* @param objectValidatorConfig A record mapping property keys to their validators (and optional pruners).
|
|
24
|
+
* @returns ValidatorWithPruner for the object.
|
|
25
|
+
*/
|
|
26
|
+
function getObjectValidatorAndPruner(objectValidatorConfig) {
|
|
27
|
+
const objectValidatorFunction = (subject) => {
|
|
28
|
+
if (!(0, checks_1.isObjectUnsafe)(subject)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
for (const key in objectValidatorConfig) {
|
|
32
|
+
const validator = getValidatorFromConfig(objectValidatorConfig[key]);
|
|
33
|
+
if (!validator(subject[key])) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
39
|
+
const objectPrunerFunction = (subject) => {
|
|
40
|
+
if ((0, checks_1.isArray)(subject) || !(0, checks_1.isObjectUnsafe)(subject)) {
|
|
41
|
+
return {
|
|
42
|
+
prunerResult: subject,
|
|
43
|
+
invalidFields: createElementInvalidField(subject),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const invalidFields = new Map();
|
|
47
|
+
// Make a shallow copy to avoid mutating the original object
|
|
48
|
+
const prunerResult = Object.assign({}, subject);
|
|
49
|
+
for (const key in objectValidatorConfig) {
|
|
50
|
+
const validator = getValidatorFromConfig(objectValidatorConfig[key]);
|
|
51
|
+
const pruner = getPrunerFromConfig(objectValidatorConfig[key]);
|
|
52
|
+
if (!validator(prunerResult[key])) {
|
|
53
|
+
if (!pruner) {
|
|
54
|
+
// If there's no pruner, mark the field invalid but retain the original value.
|
|
55
|
+
invalidFields.set(`${key}:`, prunerResult[key]);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const prunerFieldResult = pruner(prunerResult[key]);
|
|
59
|
+
prunerResult[key] = prunerFieldResult.prunerResult;
|
|
60
|
+
for (const [invalidSubKey, invalidValue] of prunerFieldResult.invalidFields) {
|
|
61
|
+
invalidFields.set(`${key}:${invalidSubKey}`, invalidValue);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { prunerResult, invalidFields };
|
|
66
|
+
};
|
|
67
|
+
return { validator: objectValidatorFunction, pruner: objectPrunerFunction };
|
|
68
|
+
}
|
|
69
|
+
exports.getObjectValidatorAndPruner = getObjectValidatorAndPruner;
|
|
70
|
+
/**
|
|
71
|
+
* Create a validator and pruner for an array of elements.
|
|
72
|
+
*
|
|
73
|
+
* - The validator ensures that each element in the array passes a common element validator.
|
|
74
|
+
* - The pruner removes or transforms invalid elements as configured by the element pruner.
|
|
75
|
+
*
|
|
76
|
+
* @param arrayElementConfig A single validator (and optionally a pruner) used for each element.
|
|
77
|
+
* @returns ValidatorWithPruner for the array.
|
|
78
|
+
*/
|
|
79
|
+
function getArrayValidatorAndPruner(arrayElementConfig) {
|
|
80
|
+
const arrayValidatorFunction = (subject) => {
|
|
81
|
+
if (!(0, checks_1.isArray)(subject)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const elementValidator = getValidatorFromConfig(arrayElementConfig);
|
|
85
|
+
return subject.every((element) => elementValidator(element));
|
|
86
|
+
};
|
|
87
|
+
const arrayPrunerFunction = (subject) => {
|
|
88
|
+
if (!(0, checks_1.isArray)(subject)) {
|
|
89
|
+
return {
|
|
90
|
+
prunerResult: subject,
|
|
91
|
+
invalidFields: createElementInvalidField(subject),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const elementValidator = getValidatorFromConfig(arrayElementConfig);
|
|
95
|
+
const elementPruner = getPrunerFromConfig(arrayElementConfig);
|
|
96
|
+
const invalidFields = new Map();
|
|
97
|
+
const prunerResult = subject
|
|
98
|
+
.map((item, index) => {
|
|
99
|
+
if (!elementValidator(item)) {
|
|
100
|
+
if (!elementPruner) {
|
|
101
|
+
invalidFields.set(`${index}:`, item);
|
|
102
|
+
return item;
|
|
103
|
+
}
|
|
104
|
+
const prunerElementResult = elementPruner(item);
|
|
105
|
+
for (const [subKey, subValue] of prunerElementResult.invalidFields) {
|
|
106
|
+
invalidFields.set(`${index}:${subKey}`, subValue);
|
|
107
|
+
}
|
|
108
|
+
return prunerElementResult.prunerResult;
|
|
109
|
+
}
|
|
110
|
+
return item;
|
|
111
|
+
})
|
|
112
|
+
.filter(checks_1.isDef);
|
|
113
|
+
return { prunerResult, invalidFields };
|
|
114
|
+
};
|
|
115
|
+
return { validator: arrayValidatorFunction, pruner: arrayPrunerFunction };
|
|
116
|
+
}
|
|
117
|
+
exports.getArrayValidatorAndPruner = getArrayValidatorAndPruner;
|
|
118
|
+
/**
|
|
119
|
+
* Creates a Map signifying that the entire `element` was invalid,
|
|
120
|
+
* with a key of `""` or some placeholder to represent the entire item.
|
|
121
|
+
*/
|
|
122
|
+
function createElementInvalidField(element) {
|
|
123
|
+
return new Map([['', element]]);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Function used in objectFieldConfig and arrayElementConfig to speficy that invalid
|
|
127
|
+
* items must be pruned/marked as undefined.
|
|
128
|
+
* @param element The data that failed validation and needs pruning.
|
|
129
|
+
*/
|
|
130
|
+
const pruneElement = (element) => {
|
|
131
|
+
return { prunerResult: undefined, invalidFields: createElementInvalidField(element) };
|
|
132
|
+
};
|
|
133
|
+
exports.pruneElement = pruneElement;
|
|
134
|
+
/**
|
|
135
|
+
* Combines a "per-element pruner" for an array’s elements with an "entire array pruner."
|
|
136
|
+
*
|
|
137
|
+
* - If the incoming data is not an array, it applies the `wholeArrayPruner`.
|
|
138
|
+
* - If it is an array, it applies the `perElementPruner` to each element.
|
|
139
|
+
*
|
|
140
|
+
* This is useful when you have specialized logic for array-level pruning
|
|
141
|
+
* (e.g., removing the entire array if it fails some overarching condition)
|
|
142
|
+
* but still want to prune individual elements if possible.
|
|
143
|
+
*
|
|
144
|
+
* @param perElementPruner A pruner for each element in the array.
|
|
145
|
+
* @param wholeArrayPruner A pruner for the entire array.
|
|
146
|
+
* @returns A Pruner that handles both array-level and element-level pruning.
|
|
147
|
+
*/
|
|
148
|
+
function liftArrayPruner(perElementPruner, wholeArrayPruner) {
|
|
149
|
+
return (data) => {
|
|
150
|
+
if (!(0, checks_1.isArray)(data)) {
|
|
151
|
+
return wholeArrayPruner(data);
|
|
152
|
+
}
|
|
153
|
+
return perElementPruner(data);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
exports.liftArrayPruner = liftArrayPruner;
|
|
157
|
+
/**
|
|
158
|
+
* Helper function to easily create a `ValidatorWithOptionalPruner`.
|
|
159
|
+
*
|
|
160
|
+
* @param validator The validation function to determine valid vs invalid data.
|
|
161
|
+
* @param pruner The optional pruner function to sanitize or remove invalid data.
|
|
162
|
+
* @returns An object containing both the validator and the (optional) pruner.
|
|
163
|
+
*/
|
|
164
|
+
function getValidatorPrunerConfig(validator, pruner) {
|
|
165
|
+
return { validator, pruner };
|
|
166
|
+
}
|
|
167
|
+
exports.getValidatorPrunerConfig = getValidatorPrunerConfig;
|