@memberjunction/react-test-harness 2.123.1 → 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.
Files changed (40) hide show
  1. package/dist/lib/component-linter.d.ts.map +1 -1
  2. package/dist/lib/component-linter.js +433 -2
  3. package/dist/lib/component-linter.js.map +1 -1
  4. package/dist/lib/constraint-validators/base-constraint-validator.d.ts +259 -0
  5. package/dist/lib/constraint-validators/base-constraint-validator.d.ts.map +1 -0
  6. package/dist/lib/constraint-validators/base-constraint-validator.js +304 -0
  7. package/dist/lib/constraint-validators/base-constraint-validator.js.map +1 -0
  8. package/dist/lib/constraint-validators/index.d.ts +21 -0
  9. package/dist/lib/constraint-validators/index.d.ts.map +1 -0
  10. package/dist/lib/constraint-validators/index.js +37 -0
  11. package/dist/lib/constraint-validators/index.js.map +1 -0
  12. package/dist/lib/constraint-validators/required-when-validator.d.ts +43 -0
  13. package/dist/lib/constraint-validators/required-when-validator.d.ts.map +1 -0
  14. package/dist/lib/constraint-validators/required-when-validator.js +97 -0
  15. package/dist/lib/constraint-validators/required-when-validator.js.map +1 -0
  16. package/dist/lib/constraint-validators/sql-where-clause-validator.d.ts +116 -0
  17. package/dist/lib/constraint-validators/sql-where-clause-validator.d.ts.map +1 -0
  18. package/dist/lib/constraint-validators/sql-where-clause-validator.js +381 -0
  19. package/dist/lib/constraint-validators/sql-where-clause-validator.js.map +1 -0
  20. package/dist/lib/constraint-validators/subset-of-entity-fields-validator.d.ts +60 -0
  21. package/dist/lib/constraint-validators/subset-of-entity-fields-validator.d.ts.map +1 -0
  22. package/dist/lib/constraint-validators/subset-of-entity-fields-validator.js +198 -0
  23. package/dist/lib/constraint-validators/subset-of-entity-fields-validator.js.map +1 -0
  24. package/dist/lib/constraint-validators/validation-context.d.ts +326 -0
  25. package/dist/lib/constraint-validators/validation-context.d.ts.map +1 -0
  26. package/dist/lib/constraint-validators/validation-context.js +14 -0
  27. package/dist/lib/constraint-validators/validation-context.js.map +1 -0
  28. package/dist/lib/prop-value-extractor.d.ts +147 -0
  29. package/dist/lib/prop-value-extractor.d.ts.map +1 -0
  30. package/dist/lib/prop-value-extractor.js +499 -0
  31. package/dist/lib/prop-value-extractor.js.map +1 -0
  32. package/dist/lib/type-context.d.ts +2 -0
  33. package/dist/lib/type-context.d.ts.map +1 -1
  34. package/dist/lib/type-context.js +22 -9
  35. package/dist/lib/type-context.js.map +1 -1
  36. package/dist/lib/type-inference-engine.d.ts +20 -0
  37. package/dist/lib/type-inference-engine.d.ts.map +1 -1
  38. package/dist/lib/type-inference-engine.js +253 -20
  39. package/dist/lib/type-inference-engine.js.map +1 -1
  40. package/package.json +13 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"required-when-validator.d.ts","sourceRoot":"","sources":["../../../src/lib/constraint-validators/required-when-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAEtG,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,qBACa,qBAAsB,SAAQ,uBAAuB;IAChE;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,kBAAkB,GAAG,mBAAmB,EAAE;CAmD5F"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ /**
3
+ * Required-When Constraint Validator
4
+ *
5
+ * Validates that a property is present when a specified condition is met.
6
+ * Used for conditional requirements like "valueField is required when aggregateMethod is 'sum'".
7
+ *
8
+ * Config:
9
+ * - condition: JavaScript expression evaluated with siblingProp as the dependent property value
10
+ * Example: "siblingProp === 'sum' || siblingProp === 'average'"
11
+ *
12
+ * Example usage in spec JSON:
13
+ * ```json
14
+ * {
15
+ * "type": "required-when",
16
+ * "dependsOn": "aggregateMethod",
17
+ * "config": {
18
+ * "condition": "siblingProp === 'sum' || siblingProp === 'average' || siblingProp === 'min' || siblingProp === 'max'"
19
+ * },
20
+ * "errorTemplate": "valueField is required when aggregateMethod is '{aggregateMethod}'"
21
+ * }
22
+ * ```
23
+ */
24
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
25
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
26
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
27
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
28
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
29
+ };
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.RequiredWhenValidator = void 0;
32
+ const global_1 = require("@memberjunction/global");
33
+ const base_constraint_validator_1 = require("./base-constraint-validator");
34
+ let RequiredWhenValidator = class RequiredWhenValidator extends base_constraint_validator_1.BaseConstraintValidator {
35
+ /**
36
+ * Get description of this validator
37
+ */
38
+ getDescription() {
39
+ return 'Validates that a property is present when a specified condition is met based on another property value';
40
+ }
41
+ /**
42
+ * Validate that a property is present when a condition is met
43
+ *
44
+ * Evaluates a JavaScript condition expression with the dependent property value,
45
+ * and checks if the current property has a value when the condition is true.
46
+ *
47
+ * @param context - Validation context containing property info and sibling props
48
+ * @param constraint - The constraint definition from the spec
49
+ * @returns Array of violations (empty if valid)
50
+ */
51
+ validate(context, constraint) {
52
+ const violations = [];
53
+ if (!constraint.dependsOn) {
54
+ return violations; // Can't validate without a dependency
55
+ }
56
+ const dependentPropValue = context.siblingProps.get(constraint.dependsOn);
57
+ // If dependent prop doesn't exist, condition doesn't apply
58
+ if (dependentPropValue === undefined || dependentPropValue === null) {
59
+ return violations;
60
+ }
61
+ const condition = constraint.config?.condition;
62
+ if (!condition || typeof condition !== 'string') {
63
+ console.warn(`required-when validator missing condition config for ${context.propertyName}`);
64
+ return violations;
65
+ }
66
+ // Evaluate the condition
67
+ let conditionMet = false;
68
+ try {
69
+ // Create a safe evaluation context
70
+ const siblingProp = dependentPropValue;
71
+ // eslint-disable-next-line no-eval
72
+ conditionMet = eval(condition);
73
+ }
74
+ catch (error) {
75
+ console.error(`Error evaluating required-when condition "${condition}":`, error);
76
+ return violations;
77
+ }
78
+ // If condition is met, check if the property has a value
79
+ if (conditionMet) {
80
+ const hasValue = context.propertyValue !== undefined &&
81
+ context.propertyValue !== null &&
82
+ context.propertyValue !== '';
83
+ if (!hasValue) {
84
+ const message = constraint.errorTemplate
85
+ ? constraint.errorTemplate.replace(`{${constraint.dependsOn}}`, String(dependentPropValue))
86
+ : `${context.propertyName} is required when ${constraint.dependsOn} is ${dependentPropValue}`;
87
+ violations.push(this.createViolation('missing-required-prop', message, 'high'));
88
+ }
89
+ }
90
+ return violations;
91
+ }
92
+ };
93
+ exports.RequiredWhenValidator = RequiredWhenValidator;
94
+ exports.RequiredWhenValidator = RequiredWhenValidator = __decorate([
95
+ (0, global_1.RegisterClass)(base_constraint_validator_1.BaseConstraintValidator, 'required-when')
96
+ ], RequiredWhenValidator);
97
+ //# sourceMappingURL=required-when-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"required-when-validator.js","sourceRoot":"","sources":["../../../src/lib/constraint-validators/required-when-validator.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;;;;;;;AAGH,mDAAuD;AACvD,2EAAsE;AAI/D,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,mDAAuB;IAChE;;OAEG;IACH,cAAc;QACZ,OAAO,wGAAwG,CAAC;IAClH,CAAC;IAED;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAA0B,EAAE,UAA8B;QACjE,MAAM,UAAU,GAA0B,EAAE,CAAC;QAE7C,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,UAAU,CAAC,CAAC,sCAAsC;QAC3D,CAAC;QAED,MAAM,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAE1E,2DAA2D;QAC3D,IAAI,kBAAkB,KAAK,SAAS,IAAI,kBAAkB,KAAK,IAAI,EAAE,CAAC;YACpE,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC;QAC/C,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,wDAAwD,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;YAC7F,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,yBAAyB;QACzB,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC;YACH,mCAAmC;YACnC,MAAM,WAAW,GAAG,kBAAkB,CAAC;YACvC,mCAAmC;YACnC,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,6CAA6C,SAAS,IAAI,EAAE,KAAK,CAAC,CAAC;YACjF,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,yDAAyD;QACzD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,KAAK,SAAS;gBACpC,OAAO,CAAC,aAAa,KAAK,IAAI;gBAC9B,OAAO,CAAC,aAAa,KAAK,EAAE,CAAC;YAE7C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,OAAO,GAAG,UAAU,CAAC,aAAa;oBACtC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,SAAS,GAAG,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;oBAC3F,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,qBAAqB,UAAU,CAAC,SAAS,OAAO,kBAAkB,EAAE,CAAC;gBAEhG,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAAC,uBAAuB,EAAE,OAAO,EAAE,MAAM,CAAC,CAC/D,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAA;AArEY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,sBAAa,EAAC,mDAAuB,EAAE,eAAe,CAAC;GAC3C,qBAAqB,CAqEjC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * SQL WHERE Clause Validator
3
+ *
4
+ * Validates SQL WHERE clauses for syntax and field references.
5
+ * Uses node-sql-parser for accurate AST-based validation with regex fallback.
6
+ *
7
+ * This validator is essential for catching errors like:
8
+ * ```jsx
9
+ * // ❌ BROKEN - LastModified doesn't exist on Products
10
+ * <EntityDataGrid
11
+ * entityName="Products"
12
+ * extraFilter="Status='Active' AND LastModified > '2024-01-01'"
13
+ * />
14
+ *
15
+ * // ✅ FIXED - CreatedAt exists on Products
16
+ * <EntityDataGrid
17
+ * entityName="Products"
18
+ * extraFilter="Status='Active' AND CreatedAt > '2024-01-01'"
19
+ * />
20
+ * ```
21
+ *
22
+ * Validation Levels:
23
+ * - **Level 1**: Field existence (IMPLEMENTED)
24
+ * - **Level 2**: Type compatibility (FUTURE)
25
+ * - **Level 3**: SQL function validation (FUTURE)
26
+ *
27
+ * Constraint Definition:
28
+ * ```json
29
+ * {
30
+ * "type": "sql-where-clause",
31
+ * "dependsOn": "entityName",
32
+ * "config": {
33
+ * "caseSensitive": false
34
+ * }
35
+ * }
36
+ * ```
37
+ */
38
+ import { PropertyConstraint, ConstraintViolation } from '@memberjunction/interactive-component-types';
39
+ import { BaseConstraintValidator } from './base-constraint-validator';
40
+ import { ValidationContext } from './validation-context';
41
+ /**
42
+ * Validates SQL WHERE clauses for syntax and field references
43
+ *
44
+ * **Depends On**: Entity name (from entityName prop)
45
+ * **Validates**: SQL WHERE clause string
46
+ * **Common Use Cases**:
47
+ * - EntityDataGrid extraFilter prop
48
+ * - RunView ExtraFilter parameter
49
+ * - Custom components with SQL filtering
50
+ *
51
+ * **Implementation**: Uses node-sql-parser (same as QueryEntity.server.ts)
52
+ * for accurate AST-based validation with regex fallback for edge cases.
53
+ */
54
+ export declare class SqlWhereClauseValidator extends BaseConstraintValidator {
55
+ /**
56
+ * SQL keywords that are not field references
57
+ * Used in regex fallback when AST parsing fails
58
+ */
59
+ private static readonly SQL_KEYWORDS;
60
+ /**
61
+ * Validate SQL WHERE clause
62
+ *
63
+ * @param context - Validation context
64
+ * @param constraint - Constraint definition
65
+ * @returns Array of violations (empty if valid)
66
+ */
67
+ validate(context: ValidationContext, constraint: PropertyConstraint): ConstraintViolation[];
68
+ /**
69
+ * Validate WHERE clause using AST parsing (Level 1: Field existence)
70
+ *
71
+ * Uses node-sql-parser to accurately extract column references.
72
+ * Pattern based on QueryEntity.server.ts (lines 305-324, 560-590)
73
+ *
74
+ * @param whereClause - SQL WHERE clause
75
+ * @param entityName - Entity name for context
76
+ * @param fieldNames - Valid field names
77
+ * @param fieldNamesLower - Lowercase field names for case-insensitive matching
78
+ * @param caseSensitive - Whether to check case sensitivity
79
+ * @param context - Validation context
80
+ * @param constraint - Constraint definition
81
+ * @returns Array of violations
82
+ */
83
+ private validateWithAST;
84
+ /**
85
+ * Extract column references from SQL AST
86
+ *
87
+ * Pattern based on QueryEntity.extractColumnReferences (lines 563-590)
88
+ * Recursively traverses the AST to find all column_ref nodes.
89
+ *
90
+ * @param expr - Expression node from AST
91
+ * @param referencedColumns - Set to collect column names
92
+ */
93
+ private extractColumnReferences;
94
+ /**
95
+ * Fallback regex-based validation for when SQL parsing fails
96
+ *
97
+ * Less accurate than AST parsing but handles edge cases.
98
+ * Violations from regex fallback have 'high' severity instead of 'critical'
99
+ * to indicate less certainty.
100
+ *
101
+ * @param whereClause - SQL WHERE clause
102
+ * @param entityName - Entity name for context
103
+ * @param fieldNames - Valid field names
104
+ * @param fieldNamesLower - Lowercase field names
105
+ * @param caseSensitive - Whether to check case sensitivity
106
+ * @param context - Validation context
107
+ * @param constraint - Constraint definition
108
+ * @returns Array of violations
109
+ */
110
+ private validateWithRegex;
111
+ /**
112
+ * Get validator description
113
+ */
114
+ getDescription(): string;
115
+ }
116
+ //# sourceMappingURL=sql-where-clause-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-where-clause-validator.d.ts","sourceRoot":"","sources":["../../../src/lib/constraint-validators/sql-where-clause-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAIzD;;;;;;;;;;;;GAYG;AACH,qBACa,uBAAwB,SAAQ,uBAAuB;IAClE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAajC;IAEH;;;;;;OAMG;IACH,QAAQ,CACN,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,kBAAkB,GAC7B,mBAAmB,EAAE;IA0ExB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,eAAe;IAiHvB;;;;;;;;OAQG;IACH,OAAO,CAAC,uBAAuB;IAwD/B;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,iBAAiB;IA6GzB;;OAEG;IACH,cAAc,IAAI,MAAM;CAGzB"}
@@ -0,0 +1,381 @@
1
+ "use strict";
2
+ /**
3
+ * SQL WHERE Clause Validator
4
+ *
5
+ * Validates SQL WHERE clauses for syntax and field references.
6
+ * Uses node-sql-parser for accurate AST-based validation with regex fallback.
7
+ *
8
+ * This validator is essential for catching errors like:
9
+ * ```jsx
10
+ * // ❌ BROKEN - LastModified doesn't exist on Products
11
+ * <EntityDataGrid
12
+ * entityName="Products"
13
+ * extraFilter="Status='Active' AND LastModified > '2024-01-01'"
14
+ * />
15
+ *
16
+ * // ✅ FIXED - CreatedAt exists on Products
17
+ * <EntityDataGrid
18
+ * entityName="Products"
19
+ * extraFilter="Status='Active' AND CreatedAt > '2024-01-01'"
20
+ * />
21
+ * ```
22
+ *
23
+ * Validation Levels:
24
+ * - **Level 1**: Field existence (IMPLEMENTED)
25
+ * - **Level 2**: Type compatibility (FUTURE)
26
+ * - **Level 3**: SQL function validation (FUTURE)
27
+ *
28
+ * Constraint Definition:
29
+ * ```json
30
+ * {
31
+ * "type": "sql-where-clause",
32
+ * "dependsOn": "entityName",
33
+ * "config": {
34
+ * "caseSensitive": false
35
+ * }
36
+ * }
37
+ * ```
38
+ */
39
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
40
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
41
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
42
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
43
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
44
+ };
45
+ var SqlWhereClauseValidator_1;
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.SqlWhereClauseValidator = void 0;
48
+ const global_1 = require("@memberjunction/global");
49
+ const base_constraint_validator_1 = require("./base-constraint-validator");
50
+ const node_sql_parser_1 = require("node-sql-parser");
51
+ /**
52
+ * Validates SQL WHERE clauses for syntax and field references
53
+ *
54
+ * **Depends On**: Entity name (from entityName prop)
55
+ * **Validates**: SQL WHERE clause string
56
+ * **Common Use Cases**:
57
+ * - EntityDataGrid extraFilter prop
58
+ * - RunView ExtraFilter parameter
59
+ * - Custom components with SQL filtering
60
+ *
61
+ * **Implementation**: Uses node-sql-parser (same as QueryEntity.server.ts)
62
+ * for accurate AST-based validation with regex fallback for edge cases.
63
+ */
64
+ let SqlWhereClauseValidator = SqlWhereClauseValidator_1 = class SqlWhereClauseValidator extends base_constraint_validator_1.BaseConstraintValidator {
65
+ /**
66
+ * Validate SQL WHERE clause
67
+ *
68
+ * @param context - Validation context
69
+ * @param constraint - Constraint definition
70
+ * @returns Array of violations (empty if valid)
71
+ */
72
+ validate(context, constraint) {
73
+ const violations = [];
74
+ // Check if value is dynamic (can't validate statically)
75
+ if (this.isDynamicValue(context.propertyValue)) {
76
+ return violations; // Skip validation
77
+ }
78
+ // WHERE clause must be a string
79
+ if (typeof context.propertyValue !== 'string') {
80
+ return violations; // Not a string - not this validator's responsibility
81
+ }
82
+ const whereClause = context.propertyValue.trim();
83
+ // Empty WHERE clause is valid
84
+ if (whereClause.length === 0) {
85
+ return violations;
86
+ }
87
+ // Get the entity name from dependent prop
88
+ const entityName = this.getDependentPropValue(context, constraint);
89
+ if (!entityName || typeof entityName !== 'string') {
90
+ // Can't validate without entity name
91
+ return violations;
92
+ }
93
+ // Check if entity exists
94
+ if (!context.hasEntity(entityName)) {
95
+ // Entity doesn't exist - not this validator's responsibility
96
+ return violations;
97
+ }
98
+ // Get entity fields
99
+ const entityFields = context.getEntityFields(entityName);
100
+ const fieldNames = entityFields.map((f) => f.name);
101
+ const fieldNamesLower = fieldNames.map((f) => f.toLowerCase());
102
+ // Extract config
103
+ const config = constraint.config || {};
104
+ const caseSensitive = config.caseSensitive === true;
105
+ // Try AST-based validation first (more accurate)
106
+ try {
107
+ const astViolations = this.validateWithAST(whereClause, entityName, fieldNames, fieldNamesLower, caseSensitive, context, constraint);
108
+ violations.push(...astViolations);
109
+ }
110
+ catch (parseError) {
111
+ // Fall back to regex if SQL parsing fails
112
+ console.warn(`SQL parsing failed for WHERE clause, using regex fallback: ${parseError.message}`);
113
+ const regexViolations = this.validateWithRegex(whereClause, entityName, fieldNames, fieldNamesLower, caseSensitive, context, constraint);
114
+ violations.push(...regexViolations);
115
+ }
116
+ return violations;
117
+ }
118
+ /**
119
+ * Validate WHERE clause using AST parsing (Level 1: Field existence)
120
+ *
121
+ * Uses node-sql-parser to accurately extract column references.
122
+ * Pattern based on QueryEntity.server.ts (lines 305-324, 560-590)
123
+ *
124
+ * @param whereClause - SQL WHERE clause
125
+ * @param entityName - Entity name for context
126
+ * @param fieldNames - Valid field names
127
+ * @param fieldNamesLower - Lowercase field names for case-insensitive matching
128
+ * @param caseSensitive - Whether to check case sensitivity
129
+ * @param context - Validation context
130
+ * @param constraint - Constraint definition
131
+ * @returns Array of violations
132
+ */
133
+ validateWithAST(whereClause, entityName, fieldNames, fieldNamesLower, caseSensitive, context, constraint) {
134
+ const violations = [];
135
+ // Parse WHERE clause using node-sql-parser
136
+ // Same pattern as QueryEntity.server.ts line 309
137
+ const parser = new node_sql_parser_1.Parser();
138
+ const ast = parser.astify(`SELECT * FROM t WHERE ${whereClause}`, {
139
+ database: 'TransactSQL',
140
+ });
141
+ // Extract column references from AST
142
+ const columnRefs = new Set();
143
+ const statements = Array.isArray(ast) ? ast : [ast];
144
+ for (const statement of statements) {
145
+ // Type guard: check if statement has a where clause
146
+ if (statement && typeof statement === 'object' && 'where' in statement && statement.where) {
147
+ this.extractColumnReferences(statement.where, columnRefs);
148
+ }
149
+ }
150
+ // Validate each column reference
151
+ for (const col of columnRefs) {
152
+ // Handle qualified names (table.column) - extract just column name
153
+ const colName = col.includes('.') ? col.split('.').pop() : col;
154
+ // Check if field exists
155
+ let fieldExists = false;
156
+ let correctCaseName = null;
157
+ if (caseSensitive) {
158
+ fieldExists = fieldNames.includes(colName);
159
+ }
160
+ else {
161
+ // Case-insensitive check
162
+ const index = fieldNamesLower.indexOf(colName.toLowerCase());
163
+ fieldExists = index !== -1;
164
+ if (fieldExists) {
165
+ correctCaseName = fieldNames[index];
166
+ }
167
+ }
168
+ if (!fieldExists) {
169
+ // Field doesn't exist - find similar fields for suggestion
170
+ const similarFields = this.findSimilar(colName, fieldNames, 3, 3);
171
+ let suggestion = '';
172
+ if (similarFields.length > 0) {
173
+ suggestion = `Did you mean: ${this.formatValueList(similarFields, 3)}?`;
174
+ }
175
+ else {
176
+ suggestion = `Available fields: ${this.formatValueList(fieldNames, 10)}`;
177
+ }
178
+ violations.push(this.createViolation('invalid-field-reference', this.applyErrorTemplate(constraint, context, `SQL WHERE clause references invalid field '${colName}' on entity '${entityName}'`, {
179
+ field: colName,
180
+ entityName,
181
+ availableFields: fieldNames.slice(0, 10).join(', '),
182
+ }), 'critical', suggestion, {
183
+ field: colName,
184
+ entityName,
185
+ availableFields: fieldNames,
186
+ similarFields,
187
+ }));
188
+ }
189
+ else if (!caseSensitive && correctCaseName && correctCaseName !== colName) {
190
+ // Field exists but case doesn't match
191
+ violations.push(this.createViolation('case-mismatch', this.applyErrorTemplate(constraint, context, `Field '${colName}' case doesn't match schema in WHERE clause. Expected '${correctCaseName}' on entity '${entityName}'`, {
192
+ field: colName,
193
+ correctCase: correctCaseName,
194
+ entityName,
195
+ }), 'medium', `Use '${correctCaseName}' instead of '${colName}'`, {
196
+ field: colName,
197
+ correctCase: correctCaseName,
198
+ entityName,
199
+ }));
200
+ }
201
+ }
202
+ return violations;
203
+ }
204
+ /**
205
+ * Extract column references from SQL AST
206
+ *
207
+ * Pattern based on QueryEntity.extractColumnReferences (lines 563-590)
208
+ * Recursively traverses the AST to find all column_ref nodes.
209
+ *
210
+ * @param expr - Expression node from AST
211
+ * @param referencedColumns - Set to collect column names
212
+ */
213
+ extractColumnReferences(expr, referencedColumns) {
214
+ if (!expr || typeof expr !== 'object')
215
+ return;
216
+ // Column reference found
217
+ if (expr.type === 'column_ref') {
218
+ // Handle qualified names (table.column)
219
+ const colName = expr.table ? `${expr.table}.${expr.column}` : expr.column;
220
+ if (typeof colName === 'string') {
221
+ referencedColumns.add(colName);
222
+ }
223
+ return;
224
+ }
225
+ // Skip SQL functions - these are not field references
226
+ // But still check function arguments for column references
227
+ if (expr.type === 'function') {
228
+ if (expr.args) {
229
+ const args = expr.args.value || expr.args;
230
+ const argsArray = Array.isArray(args) ? args : [args];
231
+ for (const arg of argsArray) {
232
+ if (arg)
233
+ this.extractColumnReferences(arg, referencedColumns);
234
+ }
235
+ }
236
+ return;
237
+ }
238
+ // Recursively traverse binary expressions (AND, OR, comparisons)
239
+ if (expr.left)
240
+ this.extractColumnReferences(expr.left, referencedColumns);
241
+ if (expr.right)
242
+ this.extractColumnReferences(expr.right, referencedColumns);
243
+ // Handle IN clauses and arrays
244
+ if (expr.value && Array.isArray(expr.value)) {
245
+ for (const item of expr.value) {
246
+ this.extractColumnReferences(item, referencedColumns);
247
+ }
248
+ }
249
+ // Handle CASE expressions
250
+ if (expr.result)
251
+ this.extractColumnReferences(expr.result, referencedColumns);
252
+ if (expr.expr)
253
+ this.extractColumnReferences(expr.expr, referencedColumns);
254
+ // Handle function args (different structure than type:'function')
255
+ if (expr.args) {
256
+ const args = Array.isArray(expr.args) ? expr.args : [expr.args];
257
+ for (const arg of args) {
258
+ if (arg && typeof arg === 'object') {
259
+ if (arg.value) {
260
+ this.extractColumnReferences(arg.value, referencedColumns);
261
+ }
262
+ else {
263
+ this.extractColumnReferences(arg, referencedColumns);
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ /**
270
+ * Fallback regex-based validation for when SQL parsing fails
271
+ *
272
+ * Less accurate than AST parsing but handles edge cases.
273
+ * Violations from regex fallback have 'high' severity instead of 'critical'
274
+ * to indicate less certainty.
275
+ *
276
+ * @param whereClause - SQL WHERE clause
277
+ * @param entityName - Entity name for context
278
+ * @param fieldNames - Valid field names
279
+ * @param fieldNamesLower - Lowercase field names
280
+ * @param caseSensitive - Whether to check case sensitivity
281
+ * @param context - Validation context
282
+ * @param constraint - Constraint definition
283
+ * @returns Array of violations
284
+ */
285
+ validateWithRegex(whereClause, entityName, fieldNames, fieldNamesLower, caseSensitive, context, constraint) {
286
+ const violations = [];
287
+ // Simple regex to extract potential field names
288
+ // Matches word characters that could be identifiers
289
+ const fieldPattern = /\b([A-Za-z_][A-Za-z0-9_]*)\b/g;
290
+ let match;
291
+ const checkedFields = new Set();
292
+ while ((match = fieldPattern.exec(whereClause)) !== null) {
293
+ const identifier = match[1];
294
+ // Skip SQL keywords
295
+ if (SqlWhereClauseValidator_1.SQL_KEYWORDS.has(identifier.toUpperCase())) {
296
+ continue;
297
+ }
298
+ // Skip duplicates
299
+ if (checkedFields.has(identifier.toLowerCase())) {
300
+ continue;
301
+ }
302
+ checkedFields.add(identifier.toLowerCase());
303
+ // Check if field exists
304
+ let fieldExists = false;
305
+ let correctCaseName = null;
306
+ if (caseSensitive) {
307
+ fieldExists = fieldNames.includes(identifier);
308
+ }
309
+ else {
310
+ const index = fieldNamesLower.indexOf(identifier.toLowerCase());
311
+ fieldExists = index !== -1;
312
+ if (fieldExists) {
313
+ correctCaseName = fieldNames[index];
314
+ }
315
+ }
316
+ if (!fieldExists) {
317
+ const similarFields = this.findSimilar(identifier, fieldNames, 3, 3);
318
+ let suggestion = '';
319
+ if (similarFields.length > 0) {
320
+ suggestion = `Did you mean: ${this.formatValueList(similarFields, 3)}?`;
321
+ }
322
+ else {
323
+ suggestion = `Available fields: ${this.formatValueList(fieldNames, 10)}`;
324
+ }
325
+ violations.push(this.createViolation('invalid-field-reference', this.applyErrorTemplate(constraint, context, `Possible invalid field '${identifier}' in WHERE clause (entity: '${entityName}')`, {
326
+ field: identifier,
327
+ entityName,
328
+ }), 'high', // Lower severity for regex fallback (less certain)
329
+ suggestion, {
330
+ field: identifier,
331
+ entityName,
332
+ availableFields: fieldNames,
333
+ similarFields,
334
+ validationMethod: 'regex-fallback',
335
+ }));
336
+ }
337
+ else if (!caseSensitive && correctCaseName && correctCaseName !== identifier) {
338
+ violations.push(this.createViolation('case-mismatch', this.applyErrorTemplate(constraint, context, `Field '${identifier}' case doesn't match schema in WHERE clause. Expected '${correctCaseName}'`, {
339
+ field: identifier,
340
+ correctCase: correctCaseName,
341
+ entityName,
342
+ }), 'medium', `Use '${correctCaseName}' instead of '${identifier}'`, {
343
+ field: identifier,
344
+ correctCase: correctCaseName,
345
+ entityName,
346
+ validationMethod: 'regex-fallback',
347
+ }));
348
+ }
349
+ }
350
+ return violations;
351
+ }
352
+ /**
353
+ * Get validator description
354
+ */
355
+ getDescription() {
356
+ return 'Validates SQL WHERE clauses for syntax and field references using AST parsing';
357
+ }
358
+ };
359
+ exports.SqlWhereClauseValidator = SqlWhereClauseValidator;
360
+ /**
361
+ * SQL keywords that are not field references
362
+ * Used in regex fallback when AST parsing fails
363
+ */
364
+ SqlWhereClauseValidator.SQL_KEYWORDS = new Set([
365
+ 'AND', 'OR', 'NOT', 'IN', 'LIKE', 'BETWEEN', 'IS', 'NULL',
366
+ 'TRUE', 'FALSE', 'ASC', 'DESC', 'CASE', 'WHEN', 'THEN', 'ELSE', 'END',
367
+ 'EXISTS', 'ALL', 'ANY', 'SOME',
368
+ // SQL Server functions - not field references
369
+ 'DATEADD', 'DATEDIFF', 'GETDATE', 'GETUTCDATE', 'SYSDATETIME',
370
+ 'CAST', 'CONVERT', 'ISNULL', 'COALESCE', 'NULLIF',
371
+ 'YEAR', 'MONTH', 'DAY', 'DATEPART', 'DATENAME',
372
+ 'LEN', 'SUBSTRING', 'CHARINDEX', 'PATINDEX', 'REPLACE',
373
+ 'UPPER', 'LOWER', 'TRIM', 'LTRIM', 'RTRIM',
374
+ 'LEFT', 'RIGHT', 'REVERSE', 'CONCAT', 'STRING_AGG',
375
+ 'COUNT', 'SUM', 'AVG', 'MIN', 'MAX',
376
+ 'ROW_NUMBER', 'RANK', 'DENSE_RANK',
377
+ ]);
378
+ exports.SqlWhereClauseValidator = SqlWhereClauseValidator = SqlWhereClauseValidator_1 = __decorate([
379
+ (0, global_1.RegisterClass)(base_constraint_validator_1.BaseConstraintValidator, 'sql-where-clause')
380
+ ], SqlWhereClauseValidator);
381
+ //# sourceMappingURL=sql-where-clause-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-where-clause-validator.js","sourceRoot":"","sources":["../../../src/lib/constraint-validators/sql-where-clause-validator.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;;;;;;;;;;AAMH,mDAAuD;AACvD,2EAAsE;AAGtE,qDAAyC;AAEzC;;;;;;;;;;;;GAYG;AAEI,IAAM,uBAAuB,+BAA7B,MAAM,uBAAwB,SAAQ,mDAAuB;IAoBlE;;;;;;OAMG;IACH,QAAQ,CACN,OAA0B,EAC1B,UAA8B;QAE9B,MAAM,UAAU,GAA0B,EAAE,CAAC;QAE7C,wDAAwD;QACxD,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/C,OAAO,UAAU,CAAC,CAAC,kBAAkB;QACvC,CAAC;QAED,gCAAgC;QAChC,IAAI,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;YAC9C,OAAO,UAAU,CAAC,CAAC,qDAAqD;QAC1E,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QAEjD,8BAA8B;QAC9B,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,0CAA0C;QAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAEnE,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;YAClD,qCAAqC;YACrC,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;YACnC,6DAA6D;YAC7D,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,oBAAoB;QACpB,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,eAAe,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAE/D,iBAAiB;QACjB,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,IAAI,EAAE,CAAC;QACvC,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,KAAK,IAAI,CAAC;QAEpD,iDAAiD;QACjD,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CACxC,WAAW,EACX,UAAU,EACV,UAAU,EACV,eAAe,EACf,aAAa,EACb,OAAO,EACP,UAAU,CACX,CAAC;YACF,UAAU,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,UAAe,EAAE,CAAC;YACzB,0CAA0C;YAC1C,OAAO,CAAC,IAAI,CAAC,8DAA8D,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;YAEjG,MAAM,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAC5C,WAAW,EACX,UAAU,EACV,UAAU,EACV,eAAe,EACf,aAAa,EACb,OAAO,EACP,UAAU,CACX,CAAC;YACF,UAAU,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACK,eAAe,CACrB,WAAmB,EACnB,UAAkB,EAClB,UAAoB,EACpB,eAAyB,EACzB,aAAsB,EACtB,OAA0B,EAC1B,UAA8B;QAE9B,MAAM,UAAU,GAA0B,EAAE,CAAC;QAE7C,2CAA2C;QAC3C,iDAAiD;QACjD,MAAM,MAAM,GAAG,IAAI,wBAAM,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,yBAAyB,WAAW,EAAE,EAAE;YAChE,QAAQ,EAAE,aAAa;SACxB,CAAC,CAAC;QAEH,qCAAqC;QACrC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAEpD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,oDAAoD;YACpD,IAAI,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,IAAI,SAAS,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;gBAC1F,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,mEAAmE;YACnE,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAEhE,wBAAwB;YACxB,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,eAAe,GAAkB,IAAI,CAAC;YAE1C,IAAI,aAAa,EAAE,CAAC;gBAClB,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,yBAAyB;gBACzB,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;gBAC7D,WAAW,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;gBAC3B,IAAI,WAAW,EAAE,CAAC;oBAChB,eAAe,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;YAED,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,2DAA2D;gBAC3D,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAClE,IAAI,UAAU,GAAG,EAAE,CAAC;gBAEpB,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,UAAU,GAAG,iBAAiB,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,CAAC;gBAC1E,CAAC;qBAAM,CAAC;oBACN,UAAU,GAAG,qBAAqB,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC3E,CAAC;gBAED,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,yBAAyB,EACzB,IAAI,CAAC,kBAAkB,CACrB,UAAU,EACV,OAAO,EACP,8CAA8C,OAAO,gBAAgB,UAAU,GAAG,EAClF;oBACE,KAAK,EAAE,OAAO;oBACd,UAAU;oBACV,eAAe,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;iBACpD,CACF,EACD,UAAU,EACV,UAAU,EACV;oBACE,KAAK,EAAE,OAAO;oBACd,UAAU;oBACV,eAAe,EAAE,UAAU;oBAC3B,aAAa;iBACd,CACF,CACF,CAAC;YACJ,CAAC;iBAAM,IAAI,CAAC,aAAa,IAAI,eAAe,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;gBAC5E,sCAAsC;gBACtC,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,eAAe,EACf,IAAI,CAAC,kBAAkB,CACrB,UAAU,EACV,OAAO,EACP,UAAU,OAAO,0DAA0D,eAAe,gBAAgB,UAAU,GAAG,EACvH;oBACE,KAAK,EAAE,OAAO;oBACd,WAAW,EAAE,eAAe;oBAC5B,UAAU;iBACX,CACF,EACD,QAAQ,EACR,QAAQ,eAAe,iBAAiB,OAAO,GAAG,EAClD;oBACE,KAAK,EAAE,OAAO;oBACd,WAAW,EAAE,eAAe;oBAC5B,UAAU;iBACX,CACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;;;;;;OAQG;IACK,uBAAuB,CAAC,IAAS,EAAE,iBAA8B;QACvE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO;QAE9C,yBAAyB;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC/B,wCAAwC;YACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YAC1E,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;YACD,OAAO;QACT,CAAC;QAED,sDAAsD;QACtD,2DAA2D;QAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC;gBAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACtD,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;oBAC5B,IAAI,GAAG;wBAAE,IAAI,CAAC,uBAAuB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC;YACD,OAAO;QACT,CAAC;QAED,iEAAiE;QACjE,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC1E,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QAE5E,+BAA+B;QAC/B,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;QAC9E,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAE1E,kEAAkE;QAClE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;oBACnC,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;wBACd,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;oBAC7D,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,uBAAuB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;oBACvD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACK,iBAAiB,CACvB,WAAmB,EACnB,UAAkB,EAClB,UAAoB,EACpB,eAAyB,EACzB,aAAsB,EACtB,OAA0B,EAC1B,UAA8B;QAE9B,MAAM,UAAU,GAA0B,EAAE,CAAC;QAE7C,gDAAgD;QAChD,oDAAoD;QACpD,MAAM,YAAY,GAAG,+BAA+B,CAAC;QAErD,IAAI,KAAK,CAAC;QACV,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;QAExC,OAAO,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACzD,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAE5B,oBAAoB;YACpB,IAAI,yBAAuB,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBACvE,SAAS;YACX,CAAC;YAED,kBAAkB;YAClB,IAAI,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAChD,SAAS;YACX,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;YAE5C,wBAAwB;YACxB,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,eAAe,GAAkB,IAAI,CAAC;YAE1C,IAAI,aAAa,EAAE,CAAC;gBAClB,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;gBAChE,WAAW,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;gBAC3B,IAAI,WAAW,EAAE,CAAC;oBAChB,eAAe,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;YAED,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBACrE,IAAI,UAAU,GAAG,EAAE,CAAC;gBAEpB,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,UAAU,GAAG,iBAAiB,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,CAAC;gBAC1E,CAAC;qBAAM,CAAC;oBACN,UAAU,GAAG,qBAAqB,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC3E,CAAC;gBAED,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,yBAAyB,EACzB,IAAI,CAAC,kBAAkB,CACrB,UAAU,EACV,OAAO,EACP,2BAA2B,UAAU,+BAA+B,UAAU,IAAI,EAClF;oBACE,KAAK,EAAE,UAAU;oBACjB,UAAU;iBACX,CACF,EACD,MAAM,EAAE,mDAAmD;gBAC3D,UAAU,EACV;oBACE,KAAK,EAAE,UAAU;oBACjB,UAAU;oBACV,eAAe,EAAE,UAAU;oBAC3B,aAAa;oBACb,gBAAgB,EAAE,gBAAgB;iBACnC,CACF,CACF,CAAC;YACJ,CAAC;iBAAM,IAAI,CAAC,aAAa,IAAI,eAAe,IAAI,eAAe,KAAK,UAAU,EAAE,CAAC;gBAC/E,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,eAAe,EACf,IAAI,CAAC,kBAAkB,CACrB,UAAU,EACV,OAAO,EACP,UAAU,UAAU,0DAA0D,eAAe,GAAG,EAChG;oBACE,KAAK,EAAE,UAAU;oBACjB,WAAW,EAAE,eAAe;oBAC5B,UAAU;iBACX,CACF,EACD,QAAQ,EACR,QAAQ,eAAe,iBAAiB,UAAU,GAAG,EACrD;oBACE,KAAK,EAAE,UAAU;oBACjB,WAAW,EAAE,eAAe;oBAC5B,UAAU;oBACV,gBAAgB,EAAE,gBAAgB;iBACnC,CACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,+EAA+E,CAAC;IACzF,CAAC;;AA3aU,0DAAuB;AAClC;;;GAGG;AACqB,oCAAY,GAAG,IAAI,GAAG,CAAC;IAC7C,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM;IACzD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;IACrE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM;IAC9B,8CAA8C;IAC9C,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa;IAC7D,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ;IACjD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU;IAC9C,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS;IACtD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAC1C,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY;IAClD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;IACnC,YAAY,EAAE,MAAM,EAAE,YAAY;CACnC,CAAC,AAbkC,CAajC;kCAlBQ,uBAAuB;IADnC,IAAA,sBAAa,EAAC,mDAAuB,EAAE,kBAAkB,CAAC;GAC9C,uBAAuB,CA4anC"}