@memberjunction/react-test-harness 2.124.0 → 2.125.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/lib/component-linter.d.ts.map +1 -1
- package/dist/lib/component-linter.js +433 -2
- package/dist/lib/component-linter.js.map +1 -1
- package/dist/lib/constraint-validators/base-constraint-validator.d.ts +259 -0
- package/dist/lib/constraint-validators/base-constraint-validator.d.ts.map +1 -0
- package/dist/lib/constraint-validators/base-constraint-validator.js +304 -0
- package/dist/lib/constraint-validators/base-constraint-validator.js.map +1 -0
- package/dist/lib/constraint-validators/index.d.ts +21 -0
- package/dist/lib/constraint-validators/index.d.ts.map +1 -0
- package/dist/lib/constraint-validators/index.js +37 -0
- package/dist/lib/constraint-validators/index.js.map +1 -0
- package/dist/lib/constraint-validators/required-when-validator.d.ts +43 -0
- package/dist/lib/constraint-validators/required-when-validator.d.ts.map +1 -0
- package/dist/lib/constraint-validators/required-when-validator.js +97 -0
- package/dist/lib/constraint-validators/required-when-validator.js.map +1 -0
- package/dist/lib/constraint-validators/sql-where-clause-validator.d.ts +116 -0
- package/dist/lib/constraint-validators/sql-where-clause-validator.d.ts.map +1 -0
- package/dist/lib/constraint-validators/sql-where-clause-validator.js +381 -0
- package/dist/lib/constraint-validators/sql-where-clause-validator.js.map +1 -0
- package/dist/lib/constraint-validators/subset-of-entity-fields-validator.d.ts +60 -0
- package/dist/lib/constraint-validators/subset-of-entity-fields-validator.d.ts.map +1 -0
- package/dist/lib/constraint-validators/subset-of-entity-fields-validator.js +198 -0
- package/dist/lib/constraint-validators/subset-of-entity-fields-validator.js.map +1 -0
- package/dist/lib/constraint-validators/validation-context.d.ts +326 -0
- package/dist/lib/constraint-validators/validation-context.d.ts.map +1 -0
- package/dist/lib/constraint-validators/validation-context.js +14 -0
- package/dist/lib/constraint-validators/validation-context.js.map +1 -0
- package/dist/lib/prop-value-extractor.d.ts +147 -0
- package/dist/lib/prop-value-extractor.d.ts.map +1 -0
- package/dist/lib/prop-value-extractor.js +499 -0
- package/dist/lib/prop-value-extractor.js.map +1 -0
- package/dist/lib/type-context.d.ts +2 -0
- package/dist/lib/type-context.d.ts.map +1 -1
- package/dist/lib/type-context.js +22 -9
- package/dist/lib/type-context.js.map +1 -1
- package/dist/lib/type-inference-engine.d.ts +20 -0
- package/dist/lib/type-inference-engine.d.ts.map +1 -1
- package/dist/lib/type-inference-engine.js +253 -20
- package/dist/lib/type-inference-engine.js.map +1 -1
- package/package.json +13 -9
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Constraint Validator
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class for all constraint validators.
|
|
5
|
+
* Validators implement business logic for validating prop values at lint-time.
|
|
6
|
+
*
|
|
7
|
+
* Key Concepts:
|
|
8
|
+
* - **Validators = Code**: Implemented as TypeScript classes
|
|
9
|
+
* - **Constraints = Metadata**: Declared in component spec JSON
|
|
10
|
+
* - **Separation**: Validator logic is separate from constraint definitions
|
|
11
|
+
*
|
|
12
|
+
* Example:
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Validator implementation (code)
|
|
15
|
+
* class SubsetOfEntityFieldsValidator extends BaseConstraintValidator {
|
|
16
|
+
* async validate(context, constraint) {
|
|
17
|
+
* // Implementation...
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* // Constraint definition (metadata in spec JSON)
|
|
22
|
+
* {
|
|
23
|
+
* "type": "subset-of-entity-fields",
|
|
24
|
+
* "dependsOn": "entityName"
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { PropertyConstraint, ConstraintViolation } from '@memberjunction/interactive-component-types';
|
|
29
|
+
import { ValidationContext } from './validation-context';
|
|
30
|
+
import { DynamicValue } from '../prop-value-extractor';
|
|
31
|
+
/**
|
|
32
|
+
* Abstract base class for constraint validators
|
|
33
|
+
*
|
|
34
|
+
* All constraint validators must extend this class and implement the validate() method.
|
|
35
|
+
*/
|
|
36
|
+
export declare abstract class BaseConstraintValidator {
|
|
37
|
+
/**
|
|
38
|
+
* Validate a prop value against a constraint
|
|
39
|
+
*
|
|
40
|
+
* This is the main method that subclasses must implement.
|
|
41
|
+
* It receives the validation context and constraint definition,
|
|
42
|
+
* and returns an array of violations (empty if valid).
|
|
43
|
+
*
|
|
44
|
+
* Note: Changed from async to sync since validators perform no actual I/O.
|
|
45
|
+
* This allows seamless integration with the synchronous linter architecture.
|
|
46
|
+
*
|
|
47
|
+
* @param context - Validation context with prop value, component spec, entities, etc.
|
|
48
|
+
* @param constraint - The constraint definition from the component spec
|
|
49
|
+
* @returns Array of violations (empty if valid)
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* class MyValidator extends BaseConstraintValidator {
|
|
54
|
+
* validate(context: ValidationContext, constraint: PropertyConstraint): ConstraintViolation[] {
|
|
55
|
+
* const violations: ConstraintViolation[] = [];
|
|
56
|
+
*
|
|
57
|
+
* // Check if value can be validated statically
|
|
58
|
+
* if (PropValueExtractor.isDynamicValue(context.propertyValue)) {
|
|
59
|
+
* return violations; // Skip - can't validate dynamic values
|
|
60
|
+
* }
|
|
61
|
+
*
|
|
62
|
+
* // Perform validation logic
|
|
63
|
+
* // ...
|
|
64
|
+
*
|
|
65
|
+
* return violations;
|
|
66
|
+
* }
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
abstract validate(context: ValidationContext, constraint: PropertyConstraint): ConstraintViolation[];
|
|
71
|
+
/**
|
|
72
|
+
* Get the name of this validator
|
|
73
|
+
*
|
|
74
|
+
* Used for debugging and error messages.
|
|
75
|
+
* Defaults to the class name, but can be overridden.
|
|
76
|
+
*
|
|
77
|
+
* @returns Validator name
|
|
78
|
+
*/
|
|
79
|
+
getName(): string;
|
|
80
|
+
/**
|
|
81
|
+
* Get a description of what this validator checks
|
|
82
|
+
*
|
|
83
|
+
* Used for documentation and error messages.
|
|
84
|
+
* Should be a brief, user-friendly description.
|
|
85
|
+
*
|
|
86
|
+
* @returns Validator description
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* getDescription() {
|
|
91
|
+
* return "Validates that array elements are valid field names for the specified entity";
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
abstract getDescription(): string;
|
|
96
|
+
/**
|
|
97
|
+
* Check if a value is dynamic (can't be validated statically)
|
|
98
|
+
*
|
|
99
|
+
* Dynamic values include identifiers (variables) and expressions (function calls, etc.)
|
|
100
|
+
* that can't be resolved at lint-time.
|
|
101
|
+
*
|
|
102
|
+
* @param value - The extracted value to check
|
|
103
|
+
* @returns True if the value is dynamic
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* if (this.isDynamicValue(context.propertyValue)) {
|
|
108
|
+
* return []; // Skip validation
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
protected isDynamicValue(value: any): value is DynamicValue;
|
|
113
|
+
/**
|
|
114
|
+
* Create a violation with consistent formatting
|
|
115
|
+
*
|
|
116
|
+
* Helper method to create ConstraintViolation objects with common fields populated.
|
|
117
|
+
*
|
|
118
|
+
* @param type - Violation type (e.g., 'invalid-field', 'type-mismatch')
|
|
119
|
+
* @param message - Error message
|
|
120
|
+
* @param severity - Severity level (default: 'high')
|
|
121
|
+
* @param suggestion - Optional fix suggestion
|
|
122
|
+
* @param metadata - Optional additional metadata
|
|
123
|
+
* @returns ConstraintViolation object
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* return [
|
|
128
|
+
* this.createViolation(
|
|
129
|
+
* 'invalid-field',
|
|
130
|
+
* `Field '${field}' does not exist on entity '${entityName}'`,
|
|
131
|
+
* 'critical',
|
|
132
|
+
* `Use one of: ${validFields.join(', ')}`,
|
|
133
|
+
* { field, entityName, validFields }
|
|
134
|
+
* )
|
|
135
|
+
* ];
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
protected createViolation(type: string, message: string, severity?: 'critical' | 'high' | 'medium' | 'low', suggestion?: string, metadata?: Record<string, any>): ConstraintViolation;
|
|
139
|
+
/**
|
|
140
|
+
* Get the dependent prop value
|
|
141
|
+
*
|
|
142
|
+
* If the constraint has a `dependsOn` field, this method retrieves
|
|
143
|
+
* the value of that dependent prop from sibling props.
|
|
144
|
+
*
|
|
145
|
+
* Returns null if:
|
|
146
|
+
* - No dependency is specified
|
|
147
|
+
* - The dependent prop is not found
|
|
148
|
+
* - The dependent prop has a dynamic value
|
|
149
|
+
*
|
|
150
|
+
* @param context - Validation context
|
|
151
|
+
* @param constraint - Constraint definition
|
|
152
|
+
* @returns The dependent prop value, or null if not available
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* // Constraint: { type: 'subset-of-entity-fields', dependsOn: 'entityName' }
|
|
157
|
+
* const entityName = this.getDependentPropValue(context, constraint);
|
|
158
|
+
* if (!entityName) {
|
|
159
|
+
* // Can't validate - entityName not provided or is dynamic
|
|
160
|
+
* return [];
|
|
161
|
+
* }
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
protected getDependentPropValue(context: ValidationContext, constraint: PropertyConstraint): any;
|
|
165
|
+
/**
|
|
166
|
+
* Format a list of values for error messages
|
|
167
|
+
*
|
|
168
|
+
* Truncates long lists with "..." and formats values nicely.
|
|
169
|
+
*
|
|
170
|
+
* @param values - Array of values
|
|
171
|
+
* @param maxItems - Maximum items to show (default: 10)
|
|
172
|
+
* @returns Formatted string
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* const fields = ['FirstName', 'LastName', 'Email', ...]; // 50 fields
|
|
177
|
+
* const formatted = this.formatValueList(fields, 5);
|
|
178
|
+
* // => "FirstName, LastName, Email, Status, JoinDate... (45 more)"
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
protected formatValueList(values: any[], maxItems?: number): string;
|
|
182
|
+
/**
|
|
183
|
+
* Apply custom error template
|
|
184
|
+
*
|
|
185
|
+
* If the constraint has an `errorTemplate`, applies it by replacing
|
|
186
|
+
* template variables with actual values.
|
|
187
|
+
*
|
|
188
|
+
* Template variables:
|
|
189
|
+
* - {property} - Property name from context
|
|
190
|
+
* - {value} - Property value from context
|
|
191
|
+
* - {constraint} - Constraint type
|
|
192
|
+
* - Custom variables from templateVars parameter
|
|
193
|
+
*
|
|
194
|
+
* @param constraint - Constraint definition
|
|
195
|
+
* @param context - Validation context
|
|
196
|
+
* @param defaultMessage - Default message to use if no template
|
|
197
|
+
* @param templateVars - Additional template variables
|
|
198
|
+
* @returns Formatted message
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* // Constraint: { errorTemplate: "Field '{field}' not found on {entityName}" }
|
|
203
|
+
* const message = this.applyErrorTemplate(
|
|
204
|
+
* constraint,
|
|
205
|
+
* context,
|
|
206
|
+
* `Field '${field}' does not exist`,
|
|
207
|
+
* { field: 'FullName', entityName: 'Members' }
|
|
208
|
+
* );
|
|
209
|
+
* // => "Field 'FullName' not found on Members"
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
protected applyErrorTemplate(constraint: PropertyConstraint, context: ValidationContext, defaultMessage: string, templateVars?: Record<string, any>): string;
|
|
213
|
+
/**
|
|
214
|
+
* Calculate Levenshtein distance between two strings
|
|
215
|
+
*
|
|
216
|
+
* Used for finding similar field names for "Did you mean?" suggestions.
|
|
217
|
+
*
|
|
218
|
+
* @param a - First string
|
|
219
|
+
* @param b - Second string
|
|
220
|
+
* @returns Edit distance
|
|
221
|
+
*/
|
|
222
|
+
protected levenshteinDistance(a: string, b: string): number;
|
|
223
|
+
/**
|
|
224
|
+
* Find similar strings using Levenshtein distance
|
|
225
|
+
*
|
|
226
|
+
* Returns strings sorted by similarity (most similar first).
|
|
227
|
+
*
|
|
228
|
+
* @param target - The target string to find matches for
|
|
229
|
+
* @param candidates - Array of candidate strings
|
|
230
|
+
* @param maxResults - Maximum number of results (default: 3)
|
|
231
|
+
* @param maxDistance - Maximum edit distance to consider (default: 3)
|
|
232
|
+
* @returns Array of similar strings, sorted by distance
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const fields = ['FirstName', 'LastName', 'Email', 'Status'];
|
|
237
|
+
* const similar = this.findSimilar('FristName', fields, 2);
|
|
238
|
+
* // => ['FirstName'] (edit distance 1)
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
protected findSimilar(target: string, candidates: string[], maxResults?: number, maxDistance?: number): string[];
|
|
242
|
+
/**
|
|
243
|
+
* Case-insensitive string comparison
|
|
244
|
+
*
|
|
245
|
+
* @param a - First string
|
|
246
|
+
* @param b - Second string
|
|
247
|
+
* @returns True if strings are equal (case-insensitive)
|
|
248
|
+
*/
|
|
249
|
+
protected equalsCaseInsensitive(a: string, b: string): boolean;
|
|
250
|
+
/**
|
|
251
|
+
* Check if array contains value (case-insensitive for strings)
|
|
252
|
+
*
|
|
253
|
+
* @param arr - Array to search
|
|
254
|
+
* @param value - Value to find
|
|
255
|
+
* @returns True if array contains the value
|
|
256
|
+
*/
|
|
257
|
+
protected includesCaseInsensitive(arr: string[], value: string): boolean;
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=base-constraint-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-constraint-validator.d.ts","sourceRoot":"","sources":["../../../src/lib/constraint-validators/base-constraint-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAsB,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE3E;;;;GAIG;AACH,8BAAsB,uBAAuB;IAC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,QAAQ,CAAC,QAAQ,CACf,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,kBAAkB,GAC7B,mBAAmB,EAAE;IAExB;;;;;;;OAOG;IACH,OAAO,IAAI,MAAM;IAIjB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,cAAc,IAAI,MAAM;IAMjC;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,YAAY;IAI3D;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,SAAS,CAAC,eAAe,CACvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAc,EACzD,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,mBAAmB;IAUtB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,SAAS,CAAC,qBAAqB,CAC7B,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,kBAAkB,GAC7B,GAAG;IAkBN;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,QAAQ,GAAE,MAAW,GAAG,MAAM;IAcvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,SAAS,CAAC,kBAAkB,CAC1B,UAAU,EAAE,kBAAkB,EAC9B,OAAO,EAAE,iBAAiB,EAC1B,cAAc,EAAE,MAAM,EACtB,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GACrC,MAAM;IAwBT;;;;;;;;OAQG;IACH,SAAS,CAAC,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IA+B3D;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,CAAC,WAAW,CACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,GAAE,MAAU,EACtB,WAAW,GAAE,MAAU,GACtB,MAAM,EAAE;IAYX;;;;;;OAMG;IACH,SAAS,CAAC,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAI9D;;;;;;OAMG;IACH,SAAS,CAAC,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;CAGzE"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Base Constraint Validator
|
|
4
|
+
*
|
|
5
|
+
* Abstract base class for all constraint validators.
|
|
6
|
+
* Validators implement business logic for validating prop values at lint-time.
|
|
7
|
+
*
|
|
8
|
+
* Key Concepts:
|
|
9
|
+
* - **Validators = Code**: Implemented as TypeScript classes
|
|
10
|
+
* - **Constraints = Metadata**: Declared in component spec JSON
|
|
11
|
+
* - **Separation**: Validator logic is separate from constraint definitions
|
|
12
|
+
*
|
|
13
|
+
* Example:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Validator implementation (code)
|
|
16
|
+
* class SubsetOfEntityFieldsValidator extends BaseConstraintValidator {
|
|
17
|
+
* async validate(context, constraint) {
|
|
18
|
+
* // Implementation...
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* // Constraint definition (metadata in spec JSON)
|
|
23
|
+
* {
|
|
24
|
+
* "type": "subset-of-entity-fields",
|
|
25
|
+
* "dependsOn": "entityName"
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.BaseConstraintValidator = void 0;
|
|
31
|
+
const prop_value_extractor_1 = require("../prop-value-extractor");
|
|
32
|
+
/**
|
|
33
|
+
* Abstract base class for constraint validators
|
|
34
|
+
*
|
|
35
|
+
* All constraint validators must extend this class and implement the validate() method.
|
|
36
|
+
*/
|
|
37
|
+
class BaseConstraintValidator {
|
|
38
|
+
/**
|
|
39
|
+
* Get the name of this validator
|
|
40
|
+
*
|
|
41
|
+
* Used for debugging and error messages.
|
|
42
|
+
* Defaults to the class name, but can be overridden.
|
|
43
|
+
*
|
|
44
|
+
* @returns Validator name
|
|
45
|
+
*/
|
|
46
|
+
getName() {
|
|
47
|
+
return this.constructor.name;
|
|
48
|
+
}
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Protected Helper Methods
|
|
51
|
+
// ============================================================================
|
|
52
|
+
/**
|
|
53
|
+
* Check if a value is dynamic (can't be validated statically)
|
|
54
|
+
*
|
|
55
|
+
* Dynamic values include identifiers (variables) and expressions (function calls, etc.)
|
|
56
|
+
* that can't be resolved at lint-time.
|
|
57
|
+
*
|
|
58
|
+
* @param value - The extracted value to check
|
|
59
|
+
* @returns True if the value is dynamic
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* if (this.isDynamicValue(context.propertyValue)) {
|
|
64
|
+
* return []; // Skip validation
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
isDynamicValue(value) {
|
|
69
|
+
return prop_value_extractor_1.PropValueExtractor.isDynamicValue(value);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a violation with consistent formatting
|
|
73
|
+
*
|
|
74
|
+
* Helper method to create ConstraintViolation objects with common fields populated.
|
|
75
|
+
*
|
|
76
|
+
* @param type - Violation type (e.g., 'invalid-field', 'type-mismatch')
|
|
77
|
+
* @param message - Error message
|
|
78
|
+
* @param severity - Severity level (default: 'high')
|
|
79
|
+
* @param suggestion - Optional fix suggestion
|
|
80
|
+
* @param metadata - Optional additional metadata
|
|
81
|
+
* @returns ConstraintViolation object
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* return [
|
|
86
|
+
* this.createViolation(
|
|
87
|
+
* 'invalid-field',
|
|
88
|
+
* `Field '${field}' does not exist on entity '${entityName}'`,
|
|
89
|
+
* 'critical',
|
|
90
|
+
* `Use one of: ${validFields.join(', ')}`,
|
|
91
|
+
* { field, entityName, validFields }
|
|
92
|
+
* )
|
|
93
|
+
* ];
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
createViolation(type, message, severity = 'high', suggestion, metadata) {
|
|
97
|
+
return {
|
|
98
|
+
type,
|
|
99
|
+
message,
|
|
100
|
+
severity,
|
|
101
|
+
suggestion,
|
|
102
|
+
metadata,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get the dependent prop value
|
|
107
|
+
*
|
|
108
|
+
* If the constraint has a `dependsOn` field, this method retrieves
|
|
109
|
+
* the value of that dependent prop from sibling props.
|
|
110
|
+
*
|
|
111
|
+
* Returns null if:
|
|
112
|
+
* - No dependency is specified
|
|
113
|
+
* - The dependent prop is not found
|
|
114
|
+
* - The dependent prop has a dynamic value
|
|
115
|
+
*
|
|
116
|
+
* @param context - Validation context
|
|
117
|
+
* @param constraint - Constraint definition
|
|
118
|
+
* @returns The dependent prop value, or null if not available
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* // Constraint: { type: 'subset-of-entity-fields', dependsOn: 'entityName' }
|
|
123
|
+
* const entityName = this.getDependentPropValue(context, constraint);
|
|
124
|
+
* if (!entityName) {
|
|
125
|
+
* // Can't validate - entityName not provided or is dynamic
|
|
126
|
+
* return [];
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
getDependentPropValue(context, constraint) {
|
|
131
|
+
if (!constraint.dependsOn) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const dependentValue = context.siblingProps.get(constraint.dependsOn);
|
|
135
|
+
if (!dependentValue) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
if (this.isDynamicValue(dependentValue)) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
return dependentValue;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Format a list of values for error messages
|
|
145
|
+
*
|
|
146
|
+
* Truncates long lists with "..." and formats values nicely.
|
|
147
|
+
*
|
|
148
|
+
* @param values - Array of values
|
|
149
|
+
* @param maxItems - Maximum items to show (default: 10)
|
|
150
|
+
* @returns Formatted string
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* const fields = ['FirstName', 'LastName', 'Email', ...]; // 50 fields
|
|
155
|
+
* const formatted = this.formatValueList(fields, 5);
|
|
156
|
+
* // => "FirstName, LastName, Email, Status, JoinDate... (45 more)"
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
formatValueList(values, maxItems = 10) {
|
|
160
|
+
if (values.length === 0) {
|
|
161
|
+
return '(none)';
|
|
162
|
+
}
|
|
163
|
+
if (values.length <= maxItems) {
|
|
164
|
+
return values.map((v) => `'${v}'`).join(', ');
|
|
165
|
+
}
|
|
166
|
+
const shown = values.slice(0, maxItems).map((v) => `'${v}'`);
|
|
167
|
+
const remaining = values.length - maxItems;
|
|
168
|
+
return `${shown.join(', ')}... (${remaining} more)`;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Apply custom error template
|
|
172
|
+
*
|
|
173
|
+
* If the constraint has an `errorTemplate`, applies it by replacing
|
|
174
|
+
* template variables with actual values.
|
|
175
|
+
*
|
|
176
|
+
* Template variables:
|
|
177
|
+
* - {property} - Property name from context
|
|
178
|
+
* - {value} - Property value from context
|
|
179
|
+
* - {constraint} - Constraint type
|
|
180
|
+
* - Custom variables from templateVars parameter
|
|
181
|
+
*
|
|
182
|
+
* @param constraint - Constraint definition
|
|
183
|
+
* @param context - Validation context
|
|
184
|
+
* @param defaultMessage - Default message to use if no template
|
|
185
|
+
* @param templateVars - Additional template variables
|
|
186
|
+
* @returns Formatted message
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* // Constraint: { errorTemplate: "Field '{field}' not found on {entityName}" }
|
|
191
|
+
* const message = this.applyErrorTemplate(
|
|
192
|
+
* constraint,
|
|
193
|
+
* context,
|
|
194
|
+
* `Field '${field}' does not exist`,
|
|
195
|
+
* { field: 'FullName', entityName: 'Members' }
|
|
196
|
+
* );
|
|
197
|
+
* // => "Field 'FullName' not found on Members"
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
applyErrorTemplate(constraint, context, defaultMessage, templateVars = {}) {
|
|
201
|
+
if (!constraint.errorTemplate) {
|
|
202
|
+
return defaultMessage;
|
|
203
|
+
}
|
|
204
|
+
let message = constraint.errorTemplate;
|
|
205
|
+
// Standard variables
|
|
206
|
+
const vars = {
|
|
207
|
+
property: context.propertyName,
|
|
208
|
+
value: prop_value_extractor_1.PropValueExtractor.describe(context.propertyValue),
|
|
209
|
+
constraint: constraint.type,
|
|
210
|
+
...templateVars,
|
|
211
|
+
};
|
|
212
|
+
// Replace template variables
|
|
213
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
214
|
+
const regex = new RegExp(`\\{${key}\\}`, 'g');
|
|
215
|
+
message = message.replace(regex, String(value));
|
|
216
|
+
}
|
|
217
|
+
return message;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Calculate Levenshtein distance between two strings
|
|
221
|
+
*
|
|
222
|
+
* Used for finding similar field names for "Did you mean?" suggestions.
|
|
223
|
+
*
|
|
224
|
+
* @param a - First string
|
|
225
|
+
* @param b - Second string
|
|
226
|
+
* @returns Edit distance
|
|
227
|
+
*/
|
|
228
|
+
levenshteinDistance(a, b) {
|
|
229
|
+
const matrix = [];
|
|
230
|
+
// Initialize first column
|
|
231
|
+
for (let i = 0; i <= b.length; i++) {
|
|
232
|
+
matrix[i] = [i];
|
|
233
|
+
}
|
|
234
|
+
// Initialize first row
|
|
235
|
+
for (let j = 0; j <= a.length; j++) {
|
|
236
|
+
matrix[0][j] = j;
|
|
237
|
+
}
|
|
238
|
+
// Fill matrix
|
|
239
|
+
for (let i = 1; i <= b.length; i++) {
|
|
240
|
+
for (let j = 1; j <= a.length; j++) {
|
|
241
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
242
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
|
|
246
|
+
matrix[i][j - 1] + 1, // insertion
|
|
247
|
+
matrix[i - 1][j] + 1 // deletion
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return matrix[b.length][a.length];
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Find similar strings using Levenshtein distance
|
|
256
|
+
*
|
|
257
|
+
* Returns strings sorted by similarity (most similar first).
|
|
258
|
+
*
|
|
259
|
+
* @param target - The target string to find matches for
|
|
260
|
+
* @param candidates - Array of candidate strings
|
|
261
|
+
* @param maxResults - Maximum number of results (default: 3)
|
|
262
|
+
* @param maxDistance - Maximum edit distance to consider (default: 3)
|
|
263
|
+
* @returns Array of similar strings, sorted by distance
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```typescript
|
|
267
|
+
* const fields = ['FirstName', 'LastName', 'Email', 'Status'];
|
|
268
|
+
* const similar = this.findSimilar('FristName', fields, 2);
|
|
269
|
+
* // => ['FirstName'] (edit distance 1)
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
findSimilar(target, candidates, maxResults = 3, maxDistance = 3) {
|
|
273
|
+
const withDistances = candidates
|
|
274
|
+
.map((candidate) => ({
|
|
275
|
+
value: candidate,
|
|
276
|
+
distance: this.levenshteinDistance(target.toLowerCase(), candidate.toLowerCase()),
|
|
277
|
+
}))
|
|
278
|
+
.filter((item) => item.distance <= maxDistance)
|
|
279
|
+
.sort((a, b) => a.distance - b.distance);
|
|
280
|
+
return withDistances.slice(0, maxResults).map((item) => item.value);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Case-insensitive string comparison
|
|
284
|
+
*
|
|
285
|
+
* @param a - First string
|
|
286
|
+
* @param b - Second string
|
|
287
|
+
* @returns True if strings are equal (case-insensitive)
|
|
288
|
+
*/
|
|
289
|
+
equalsCaseInsensitive(a, b) {
|
|
290
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Check if array contains value (case-insensitive for strings)
|
|
294
|
+
*
|
|
295
|
+
* @param arr - Array to search
|
|
296
|
+
* @param value - Value to find
|
|
297
|
+
* @returns True if array contains the value
|
|
298
|
+
*/
|
|
299
|
+
includesCaseInsensitive(arr, value) {
|
|
300
|
+
return arr.some((item) => this.equalsCaseInsensitive(item, value));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
exports.BaseConstraintValidator = BaseConstraintValidator;
|
|
304
|
+
//# sourceMappingURL=base-constraint-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-constraint-validator.js","sourceRoot":"","sources":["../../../src/lib/constraint-validators/base-constraint-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constraint Validators Module
|
|
3
|
+
*
|
|
4
|
+
* This module provides the infrastructure for validating component props
|
|
5
|
+
* against business rules defined in component specifications.
|
|
6
|
+
*
|
|
7
|
+
* Validators use MemberJunction's @RegisterClass decorator for automatic discovery.
|
|
8
|
+
* Each validator is registered with BaseConstraintValidator and its constraint type as the key.
|
|
9
|
+
*
|
|
10
|
+
* Key exports:
|
|
11
|
+
* - BaseConstraintValidator: Abstract base class for all validators
|
|
12
|
+
* - ValidationContext: Context passed to validators
|
|
13
|
+
* - Entity/Query metadata types
|
|
14
|
+
* - Concrete validator implementations (auto-registered via @RegisterClass)
|
|
15
|
+
*/
|
|
16
|
+
export * from './base-constraint-validator';
|
|
17
|
+
export * from './validation-context';
|
|
18
|
+
export * from './subset-of-entity-fields-validator';
|
|
19
|
+
export * from './sql-where-clause-validator';
|
|
20
|
+
export * from './required-when-validator';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/constraint-validators/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,qCAAqC,CAAC;AACpD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Constraint Validators Module
|
|
4
|
+
*
|
|
5
|
+
* This module provides the infrastructure for validating component props
|
|
6
|
+
* against business rules defined in component specifications.
|
|
7
|
+
*
|
|
8
|
+
* Validators use MemberJunction's @RegisterClass decorator for automatic discovery.
|
|
9
|
+
* Each validator is registered with BaseConstraintValidator and its constraint type as the key.
|
|
10
|
+
*
|
|
11
|
+
* Key exports:
|
|
12
|
+
* - BaseConstraintValidator: Abstract base class for all validators
|
|
13
|
+
* - ValidationContext: Context passed to validators
|
|
14
|
+
* - Entity/Query metadata types
|
|
15
|
+
* - Concrete validator implementations (auto-registered via @RegisterClass)
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
29
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
__exportStar(require("./base-constraint-validator"), exports);
|
|
33
|
+
__exportStar(require("./validation-context"), exports);
|
|
34
|
+
__exportStar(require("./subset-of-entity-fields-validator"), exports);
|
|
35
|
+
__exportStar(require("./sql-where-clause-validator"), exports);
|
|
36
|
+
__exportStar(require("./required-when-validator"), exports);
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/constraint-validators/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;;;;;;;;;;;;;;AAEH,8DAA4C;AAC5C,uDAAqC;AACrC,sEAAoD;AACpD,+DAA6C;AAC7C,4DAA0C"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Required-When Constraint Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates that a property is present when a specified condition is met.
|
|
5
|
+
* Used for conditional requirements like "valueField is required when aggregateMethod is 'sum'".
|
|
6
|
+
*
|
|
7
|
+
* Config:
|
|
8
|
+
* - condition: JavaScript expression evaluated with siblingProp as the dependent property value
|
|
9
|
+
* Example: "siblingProp === 'sum' || siblingProp === 'average'"
|
|
10
|
+
*
|
|
11
|
+
* Example usage in spec JSON:
|
|
12
|
+
* ```json
|
|
13
|
+
* {
|
|
14
|
+
* "type": "required-when",
|
|
15
|
+
* "dependsOn": "aggregateMethod",
|
|
16
|
+
* "config": {
|
|
17
|
+
* "condition": "siblingProp === 'sum' || siblingProp === 'average' || siblingProp === 'min' || siblingProp === 'max'"
|
|
18
|
+
* },
|
|
19
|
+
* "errorTemplate": "valueField is required when aggregateMethod is '{aggregateMethod}'"
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { PropertyConstraint, ConstraintViolation } from '@memberjunction/interactive-component-types';
|
|
24
|
+
import { BaseConstraintValidator } from './base-constraint-validator';
|
|
25
|
+
import { ValidationContext } from './validation-context';
|
|
26
|
+
export declare class RequiredWhenValidator extends BaseConstraintValidator {
|
|
27
|
+
/**
|
|
28
|
+
* Get description of this validator
|
|
29
|
+
*/
|
|
30
|
+
getDescription(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Validate that a property is present when a condition is met
|
|
33
|
+
*
|
|
34
|
+
* Evaluates a JavaScript condition expression with the dependent property value,
|
|
35
|
+
* and checks if the current property has a value when the condition is true.
|
|
36
|
+
*
|
|
37
|
+
* @param context - Validation context containing property info and sibling props
|
|
38
|
+
* @param constraint - The constraint definition from the spec
|
|
39
|
+
* @returns Array of violations (empty if valid)
|
|
40
|
+
*/
|
|
41
|
+
validate(context: ValidationContext, constraint: PropertyConstraint): ConstraintViolation[];
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=required-when-validator.d.ts.map
|