attio-mcp 1.3.5 → 1.4.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/CHANGELOG.md +263 -9
- package/README.md +315 -235
- package/dist/api/attio-client.d.ts +13 -3
- package/dist/api/attio-client.d.ts.map +1 -1
- package/dist/api/attio-client.js +37 -7
- package/dist/api/attio-client.js.map +1 -1
- package/dist/api/attribute-types.d.ts.map +1 -1
- package/dist/api/attribute-types.js +59 -29
- package/dist/api/attribute-types.js.map +1 -1
- package/dist/api/client-context.d.ts.map +1 -1
- package/dist/api/client-context.js +28 -42
- package/dist/api/client-context.js.map +1 -1
- package/dist/api/operations/batch.d.ts.map +1 -1
- package/dist/api/operations/batch.js +3 -1
- package/dist/api/operations/batch.js.map +1 -1
- package/dist/cli/commands/generate-skill.d.ts +28 -0
- package/dist/cli/commands/generate-skill.d.ts.map +1 -0
- package/dist/cli/commands/generate-skill.js +101 -0
- package/dist/cli/commands/generate-skill.js.map +1 -0
- package/dist/cli/discover.js +65 -0
- package/dist/cli/discover.js.map +1 -1
- package/dist/config/deal-defaults.d.ts +2 -2
- package/dist/config/deal-defaults.d.ts.map +1 -1
- package/dist/config/deal-defaults.js +15 -6
- package/dist/config/deal-defaults.js.map +1 -1
- package/dist/config/tool-aliases.d.ts +12 -0
- package/dist/config/tool-aliases.d.ts.map +1 -1
- package/dist/config/tool-aliases.js +213 -69
- package/dist/config/tool-aliases.js.map +1 -1
- package/dist/constants/tool-names.d.ts +84 -0
- package/dist/constants/tool-names.d.ts.map +1 -0
- package/dist/constants/tool-names.js +81 -0
- package/dist/constants/tool-names.js.map +1 -0
- package/dist/constants/universal.constants.d.ts +24 -0
- package/dist/constants/universal.constants.d.ts.map +1 -1
- package/dist/constants/universal.constants.js +81 -9
- package/dist/constants/universal.constants.js.map +1 -1
- package/dist/handlers/tool-configs/tasks.d.ts.map +1 -1
- package/dist/handlers/tool-configs/tasks.js +28 -0
- package/dist/handlers/tool-configs/tasks.js.map +1 -1
- package/dist/handlers/tool-configs/universal/batch-search.js +4 -4
- package/dist/handlers/tool-configs/universal/core/crud-error-handlers.d.ts +26 -4
- package/dist/handlers/tool-configs/universal/core/crud-error-handlers.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/crud-error-handlers.js +181 -21
- package/dist/handlers/tool-configs/universal/core/crud-error-handlers.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/crud-operations.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/crud-operations.js +52 -13
- package/dist/handlers/tool-configs/universal/core/crud-operations.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/detailed-info-operations.js +3 -3
- package/dist/handlers/tool-configs/universal/core/detailed-info-operations.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/error-enhancers/attribute-enhancer.d.ts +17 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/attribute-enhancer.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/attribute-enhancer.js +118 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/attribute-enhancer.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/complex-type-enhancer.d.ts +14 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/complex-type-enhancer.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/complex-type-enhancer.js +77 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/complex-type-enhancer.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/index.d.ts +24 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/index.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/index.js +35 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/index.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/record-reference-enhancer.d.ts +15 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/record-reference-enhancer.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/record-reference-enhancer.js +108 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/record-reference-enhancer.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.d.ts +14 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.js +91 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.d.ts +14 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.js +118 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/types.d.ts +77 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/types.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/types.js +42 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/types.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/uniqueness-enhancer.d.ts +15 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/uniqueness-enhancer.d.ts.map +1 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/uniqueness-enhancer.js +109 -0
- package/dist/handlers/tool-configs/universal/core/error-enhancers/uniqueness-enhancer.js.map +1 -0
- package/dist/handlers/tool-configs/universal/core/index.d.ts +63 -22
- package/dist/handlers/tool-configs/universal/core/index.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/index.js +24 -22
- package/dist/handlers/tool-configs/universal/core/index.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/metadata-operations.d.ts +43 -1
- package/dist/handlers/tool-configs/universal/core/metadata-operations.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/metadata-operations.js +117 -11
- package/dist/handlers/tool-configs/universal/core/metadata-operations.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/notes-operations.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/notes-operations.js +27 -12
- package/dist/handlers/tool-configs/universal/core/notes-operations.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/record-details-operations.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/record-details-operations.js +20 -3
- package/dist/handlers/tool-configs/universal/core/record-details-operations.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/search-operations.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/search-operations.js +11 -4
- package/dist/handlers/tool-configs/universal/core/search-operations.js.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/constants/companies.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/constants/companies.js +32 -9
- package/dist/handlers/tool-configs/universal/field-mapper/constants/companies.js.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/constants/deals.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/constants/deals.js +45 -6
- package/dist/handlers/tool-configs/universal/field-mapper/constants/deals.js.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/constants/people.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/constants/people.js +36 -5
- package/dist/handlers/tool-configs/universal/field-mapper/constants/people.js.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/transformers/value-transformer.d.ts +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/transformers/value-transformer.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/transformers/value-transformer.js +17 -1
- package/dist/handlers/tool-configs/universal/field-mapper/transformers/value-transformer.js.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/validators/field-validator.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/field-mapper/validators/field-validator.js +3 -1
- package/dist/handlers/tool-configs/universal/field-mapper/validators/field-validator.js.map +1 -1
- package/dist/handlers/tool-configs/universal/index.d.ts +75 -34
- package/dist/handlers/tool-configs/universal/index.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/index.js +58 -58
- package/dist/handlers/tool-configs/universal/index.js.map +1 -1
- package/dist/handlers/tool-configs/universal/operations/advanced-search.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/operations/advanced-search.js +5 -4
- package/dist/handlers/tool-configs/universal/operations/advanced-search.js.map +1 -1
- package/dist/handlers/tool-configs/universal/operations/batch-operations.js +3 -3
- package/dist/handlers/tool-configs/universal/operations/content-search.js +3 -3
- package/dist/handlers/tool-configs/universal/operations/index.d.ts +10 -10
- package/dist/handlers/tool-configs/universal/operations/index.js +15 -15
- package/dist/handlers/tool-configs/universal/operations/relationship-search.js +3 -3
- package/dist/handlers/tool-configs/universal/operations/timeframe-search.js +3 -3
- package/dist/handlers/tool-configs/universal/schemas/utility-schemas.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/utility-schemas.js +5 -2
- package/dist/handlers/tool-configs/universal/schemas/utility-schemas.js.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/validation-schemas.d.ts +29 -0
- package/dist/handlers/tool-configs/universal/schemas/validation-schemas.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/validation-schemas.js +28 -0
- package/dist/handlers/tool-configs/universal/schemas/validation-schemas.js.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas.d.ts +1 -1
- package/dist/handlers/tool-configs/universal/schemas.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas.js +1 -1
- package/dist/handlers/tool-configs/universal/schemas.js.map +1 -1
- package/dist/handlers/tool-configs/universal/shared-handlers.d.ts +20 -1
- package/dist/handlers/tool-configs/universal/shared-handlers.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/shared-handlers.js +216 -0
- package/dist/handlers/tool-configs/universal/shared-handlers.js.map +1 -1
- package/dist/handlers/tool-configs/universal/smithery-diagnostics.js +2 -2
- package/dist/handlers/tool-configs/universal/types.d.ts +9 -0
- package/dist/handlers/tool-configs/universal/types.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/validators/schema-validator.d.ts +11 -0
- package/dist/handlers/tool-configs/universal/validators/schema-validator.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/validators/schema-validator.js +63 -9
- package/dist/handlers/tool-configs/universal/validators/schema-validator.js.map +1 -1
- package/dist/handlers/tool-types.d.ts +9 -0
- package/dist/handlers/tool-types.d.ts.map +1 -1
- package/dist/handlers/tools/dispatcher/core.d.ts.map +1 -1
- package/dist/handlers/tools/dispatcher/core.js +24 -5
- package/dist/handlers/tools/dispatcher/core.js.map +1 -1
- package/dist/handlers/tools/formatters.d.ts +8 -1
- package/dist/handlers/tools/formatters.d.ts.map +1 -1
- package/dist/handlers/tools/formatters.js +30 -14
- package/dist/handlers/tools/formatters.js.map +1 -1
- package/dist/handlers/tools/registry.d.ts +125 -84
- package/dist/handlers/tools/registry.d.ts.map +1 -1
- package/dist/handlers/tools/registry.js +14 -9
- package/dist/handlers/tools/registry.js.map +1 -1
- package/dist/handlers/tools/standards/index.d.ts.map +1 -1
- package/dist/handlers/tools/standards/index.js +19 -11
- package/dist/handlers/tools/standards/index.js.map +1 -1
- package/dist/objects/companies/attributes.d.ts +5 -0
- package/dist/objects/companies/attributes.d.ts.map +1 -1
- package/dist/objects/companies/attributes.js +45 -31
- package/dist/objects/companies/attributes.js.map +1 -1
- package/dist/server/createServer.d.ts.map +1 -1
- package/dist/server/createServer.js +4 -3
- package/dist/server/createServer.js.map +1 -1
- package/dist/services/ErrorService.js +3 -3
- package/dist/services/ErrorService.js.map +1 -1
- package/dist/services/UniversalCreateService.d.ts.map +1 -1
- package/dist/services/UniversalCreateService.js +136 -12
- package/dist/services/UniversalCreateService.js.map +1 -1
- package/dist/services/UniversalSearchService.d.ts +4 -25
- package/dist/services/UniversalSearchService.d.ts.map +1 -1
- package/dist/services/UniversalSearchService.js +14 -324
- package/dist/services/UniversalSearchService.js.map +1 -1
- package/dist/services/UniversalUpdateService.d.ts +15 -4
- package/dist/services/UniversalUpdateService.d.ts.map +1 -1
- package/dist/services/UniversalUpdateService.js +79 -151
- package/dist/services/UniversalUpdateService.js.map +1 -1
- package/dist/services/create/factory.d.ts.map +1 -1
- package/dist/services/create/factory.js +2 -1
- package/dist/services/create/factory.js.map +1 -1
- package/dist/services/metadata/AttributeOptionsService.d.ts +38 -0
- package/dist/services/metadata/AttributeOptionsService.d.ts.map +1 -0
- package/dist/services/metadata/AttributeOptionsService.js +92 -0
- package/dist/services/metadata/AttributeOptionsService.js.map +1 -0
- package/dist/services/metadata/index.d.ts +1 -0
- package/dist/services/metadata/index.d.ts.map +1 -1
- package/dist/services/metadata/index.js +1 -0
- package/dist/services/metadata/index.js.map +1 -1
- package/dist/services/search/QueryApiService.d.ts +27 -0
- package/dist/services/search/QueryApiService.d.ts.map +1 -0
- package/dist/services/search/QueryApiService.js +144 -0
- package/dist/services/search/QueryApiService.js.map +1 -0
- package/dist/services/search/RecordsSearchService.d.ts +27 -0
- package/dist/services/search/RecordsSearchService.d.ts.map +1 -0
- package/dist/services/search/RecordsSearchService.js +122 -0
- package/dist/services/search/RecordsSearchService.js.map +1 -0
- package/dist/services/search/SearchCoordinator.d.ts +41 -0
- package/dist/services/search/SearchCoordinator.d.ts.map +1 -0
- package/dist/services/search/SearchCoordinator.js +83 -0
- package/dist/services/search/SearchCoordinator.js.map +1 -0
- package/dist/services/search/StrategyFactory.d.ts +31 -0
- package/dist/services/search/StrategyFactory.d.ts.map +1 -0
- package/dist/services/search/StrategyFactory.js +100 -0
- package/dist/services/search/StrategyFactory.js.map +1 -0
- package/dist/services/skill-generator/OutputWriterService.d.ts +41 -0
- package/dist/services/skill-generator/OutputWriterService.d.ts.map +1 -0
- package/dist/services/skill-generator/OutputWriterService.js +100 -0
- package/dist/services/skill-generator/OutputWriterService.js.map +1 -0
- package/dist/services/skill-generator/SchemaFormatterService.d.ts +61 -0
- package/dist/services/skill-generator/SchemaFormatterService.d.ts.map +1 -0
- package/dist/services/skill-generator/SchemaFormatterService.js +168 -0
- package/dist/services/skill-generator/SchemaFormatterService.js.map +1 -0
- package/dist/services/skill-generator/WorkspaceSchemaService.d.ts +84 -0
- package/dist/services/skill-generator/WorkspaceSchemaService.d.ts.map +1 -0
- package/dist/services/skill-generator/WorkspaceSchemaService.js +292 -0
- package/dist/services/skill-generator/WorkspaceSchemaService.js.map +1 -0
- package/dist/services/skill-generator/index.d.ts +12 -0
- package/dist/services/skill-generator/index.d.ts.map +1 -0
- package/dist/services/skill-generator/index.js +11 -0
- package/dist/services/skill-generator/index.js.map +1 -0
- package/dist/services/skill-generator/types.d.ts +137 -0
- package/dist/services/skill-generator/types.d.ts.map +1 -0
- package/dist/services/skill-generator/types.js +10 -0
- package/dist/services/skill-generator/types.js.map +1 -0
- package/dist/services/update/FieldPersistenceHandler.d.ts +101 -0
- package/dist/services/update/FieldPersistenceHandler.d.ts.map +1 -0
- package/dist/services/update/FieldPersistenceHandler.js +198 -0
- package/dist/services/update/FieldPersistenceHandler.js.map +1 -0
- package/dist/services/update/FieldValidationHandler.d.ts +77 -0
- package/dist/services/update/FieldValidationHandler.d.ts.map +1 -0
- package/dist/services/update/FieldValidationHandler.js +157 -0
- package/dist/services/update/FieldValidationHandler.js.map +1 -0
- package/dist/services/update/MetadataResolver.d.ts +50 -0
- package/dist/services/update/MetadataResolver.d.ts.map +1 -0
- package/dist/services/update/MetadataResolver.js +110 -0
- package/dist/services/update/MetadataResolver.js.map +1 -0
- package/dist/services/update/UpdateOrchestrator.d.ts +37 -0
- package/dist/services/update/UpdateOrchestrator.d.ts.map +1 -0
- package/dist/services/update/UpdateOrchestrator.js +58 -0
- package/dist/services/update/UpdateOrchestrator.js.map +1 -0
- package/dist/services/update/UpdateValidation.d.ts +5 -1
- package/dist/services/update/UpdateValidation.d.ts.map +1 -1
- package/dist/services/update/UpdateValidation.js +46 -14
- package/dist/services/update/UpdateValidation.js.map +1 -1
- package/dist/services/value-transformer/index.d.ts +57 -0
- package/dist/services/value-transformer/index.d.ts.map +1 -0
- package/dist/services/value-transformer/index.js +326 -0
- package/dist/services/value-transformer/index.js.map +1 -0
- package/dist/services/value-transformer/multi-select-transformer.d.ts +63 -0
- package/dist/services/value-transformer/multi-select-transformer.d.ts.map +1 -0
- package/dist/services/value-transformer/multi-select-transformer.js +144 -0
- package/dist/services/value-transformer/multi-select-transformer.js.map +1 -0
- package/dist/services/value-transformer/record-reference-transformer.d.ts +43 -0
- package/dist/services/value-transformer/record-reference-transformer.d.ts.map +1 -0
- package/dist/services/value-transformer/record-reference-transformer.js +245 -0
- package/dist/services/value-transformer/record-reference-transformer.js.map +1 -0
- package/dist/services/value-transformer/select-transformer.d.ts +48 -0
- package/dist/services/value-transformer/select-transformer.d.ts.map +1 -0
- package/dist/services/value-transformer/select-transformer.js +232 -0
- package/dist/services/value-transformer/select-transformer.js.map +1 -0
- package/dist/services/value-transformer/status-transformer.d.ts +32 -0
- package/dist/services/value-transformer/status-transformer.d.ts.map +1 -0
- package/dist/services/value-transformer/status-transformer.js +294 -0
- package/dist/services/value-transformer/status-transformer.js.map +1 -0
- package/dist/services/value-transformer/types.d.ts +100 -0
- package/dist/services/value-transformer/types.d.ts.map +1 -0
- package/dist/services/value-transformer/types.js +6 -0
- package/dist/services/value-transformer/types.js.map +1 -0
- package/dist/templates/skill/SKILL.template.md +78 -0
- package/dist/templates/skill/attribute-reference.template.md +126 -0
- package/dist/templates/skill/complex-types.template.md +255 -0
- package/dist/utils/client-resolver.d.ts.map +1 -1
- package/dist/utils/client-resolver.js +8 -16
- package/dist/utils/client-resolver.js.map +1 -1
- package/dist/utils/complex-type-validation.d.ts +16 -0
- package/dist/utils/complex-type-validation.d.ts.map +1 -0
- package/dist/utils/complex-type-validation.js +196 -0
- package/dist/utils/complex-type-validation.js.map +1 -0
- package/dist/utils/error-utilities.d.ts.map +1 -1
- package/dist/utils/error-utilities.js +16 -9
- package/dist/utils/error-utilities.js.map +1 -1
- package/dist/utils/location-normalizer.d.ts +26 -0
- package/dist/utils/location-normalizer.d.ts.map +1 -0
- package/dist/utils/location-normalizer.js +39 -0
- package/dist/utils/location-normalizer.js.map +1 -0
- package/dist/utils/metadata-utils.d.ts +27 -0
- package/dist/utils/metadata-utils.d.ts.map +1 -0
- package/dist/utils/metadata-utils.js +59 -0
- package/dist/utils/metadata-utils.js.map +1 -0
- package/dist/utils/personal-name-parser.d.ts.map +1 -1
- package/dist/utils/personal-name-parser.js +26 -17
- package/dist/utils/personal-name-parser.js.map +1 -1
- package/dist/validators/company/field_detector.d.ts.map +1 -1
- package/dist/validators/company/field_detector.js +5 -0
- package/dist/validators/company/field_detector.js.map +1 -1
- package/package.json +28 -25
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FieldPersistenceHandler - Post-update field verification
|
|
3
|
+
*
|
|
4
|
+
* Extracted from UniversalUpdateService to separate verification concerns.
|
|
5
|
+
* Handles field persistence checking with configurable strictness.
|
|
6
|
+
*
|
|
7
|
+
* **Verification Modes** (controlled by `ENABLE_FIELD_VERIFICATION` env var):
|
|
8
|
+
* - **Enabled** (default): Any value except `'false'` enables verification
|
|
9
|
+
* - **Disabled**: Set to `'false'` to skip verification entirely
|
|
10
|
+
*
|
|
11
|
+
* **Strictness Modes** (controlled by `STRICT_FIELD_VALIDATION` env var):
|
|
12
|
+
* - **Strict**: `'true'` - Logs all discrepancies (cosmetic + semantic)
|
|
13
|
+
* - **Standard** (default): `'false'` - Logs only semantic mismatches
|
|
14
|
+
*
|
|
15
|
+
* **Semantic vs Cosmetic Mismatches**:
|
|
16
|
+
* - Cosmetic: Format differences with same logical value (e.g., "Demo" vs {title: "Demo"})
|
|
17
|
+
* - Semantic: Actual data loss or corruption (e.g., "Demo" vs "Qualified", missing data)
|
|
18
|
+
*
|
|
19
|
+
* @see Issue #984 - Modularize UniversalUpdateService (831→220 lines)
|
|
20
|
+
* @see PR #1006 Phase 3.2 - Enhanced JSDoc for verification behavior
|
|
21
|
+
*/
|
|
22
|
+
import { UpdateValidation } from './UpdateValidation.js';
|
|
23
|
+
import { debug, error as logError } from '../../utils/logger.js';
|
|
24
|
+
import { UniversalValidationError, ErrorType, } from '../../handlers/tool-configs/universal/schemas.js';
|
|
25
|
+
/**
|
|
26
|
+
* FieldPersistenceHandler - Post-update verification orchestration
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Standard mode (semantic mismatches only)
|
|
31
|
+
* const result = await FieldPersistenceHandler.verifyPersistence(
|
|
32
|
+
* UniversalResourceType.COMPANIES,
|
|
33
|
+
* 'company-123',
|
|
34
|
+
* { stage: 'Demo' }
|
|
35
|
+
* );
|
|
36
|
+
* // Cosmetic mismatch "Demo" vs {title: "Demo"} → not logged
|
|
37
|
+
* // Semantic mismatch "Demo" vs "Qualified" → logged
|
|
38
|
+
*
|
|
39
|
+
* // Strict mode (all mismatches)
|
|
40
|
+
* process.env.STRICT_FIELD_VALIDATION = 'true';
|
|
41
|
+
* // Both cosmetic and semantic mismatches logged
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export class FieldPersistenceHandler {
|
|
45
|
+
/**
|
|
46
|
+
* Verify that fields were persisted correctly after update
|
|
47
|
+
*
|
|
48
|
+
* Supports three modes:
|
|
49
|
+
* 1. Disabled: ENABLE_FIELD_VERIFICATION=false (skip completely)
|
|
50
|
+
* 2. Warn-only: Default, logs discrepancies as warnings
|
|
51
|
+
* 3. Strict: STRICT_FIELD_VALIDATION=true, throws on mismatch
|
|
52
|
+
*
|
|
53
|
+
* @param resourceType - Resource type being verified
|
|
54
|
+
* @param recordId - ID of the updated record
|
|
55
|
+
* @param expectedData - Expected field values after update
|
|
56
|
+
* @param actualRecord - Optional actual record values. If not provided, will be fetched from API
|
|
57
|
+
* @param options - Verification options
|
|
58
|
+
* @returns Verification result with verified status, warnings, and discrepancies
|
|
59
|
+
* @throws UniversalValidationError if strict mode enabled and verification fails
|
|
60
|
+
*/
|
|
61
|
+
static async verifyPersistence(resourceType, recordId, expectedData, actualRecord, options = {}) {
|
|
62
|
+
const result = {
|
|
63
|
+
verified: true,
|
|
64
|
+
warnings: [],
|
|
65
|
+
discrepancies: [],
|
|
66
|
+
actualValues: {},
|
|
67
|
+
};
|
|
68
|
+
// Check if verification is disabled globally
|
|
69
|
+
if (options.skip || process.env.ENABLE_FIELD_VERIFICATION === 'false') {
|
|
70
|
+
result.warnings.push('Field persistence verification skipped (disabled via config)');
|
|
71
|
+
debug('FieldPersistenceHandler', 'Verification skipped', {
|
|
72
|
+
resourceType,
|
|
73
|
+
recordId,
|
|
74
|
+
reason: 'disabled',
|
|
75
|
+
});
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
// Fetch actualRecord if not provided
|
|
79
|
+
let recordData = actualRecord;
|
|
80
|
+
if (!recordData) {
|
|
81
|
+
try {
|
|
82
|
+
const record = await UpdateValidation.fetchRecordForVerification(resourceType, recordId);
|
|
83
|
+
if (!record) {
|
|
84
|
+
result.warnings.push('Could not fetch record for verification: Record not found');
|
|
85
|
+
debug('FieldPersistenceHandler', 'Record not found for verification', { resourceType, recordId });
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
recordData = record.values || {};
|
|
89
|
+
debug('FieldPersistenceHandler', 'Fetched record for verification', {
|
|
90
|
+
resourceType,
|
|
91
|
+
recordId,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
96
|
+
result.warnings.push(`Could not fetch record for verification: ${errorMessage}`);
|
|
97
|
+
debug('FieldPersistenceHandler', 'Failed to fetch record for verification', { resourceType, recordId, error: errorMessage });
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
result.actualValues = recordData || {};
|
|
102
|
+
try {
|
|
103
|
+
// Perform verification using existing UpdateValidation service
|
|
104
|
+
const verification = await UpdateValidation.verifyFieldPersistence(resourceType, recordId, expectedData);
|
|
105
|
+
result.verified = verification.verified;
|
|
106
|
+
result.warnings.push(...verification.warnings);
|
|
107
|
+
if (!verification.verified) {
|
|
108
|
+
const isStrictMode = options.strict !== undefined
|
|
109
|
+
? options.strict
|
|
110
|
+
: process.env.STRICT_FIELD_VALIDATION === 'true';
|
|
111
|
+
const includeCosmetic = options.includeCosmetic || isStrictMode;
|
|
112
|
+
// Filter discrepancies based on mode
|
|
113
|
+
if (includeCosmetic) {
|
|
114
|
+
// Include all discrepancies (cosmetic + semantic)
|
|
115
|
+
result.discrepancies.push(...verification.discrepancies);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// Filter out cosmetic mismatches (e.g., "Demo" vs {title: "Demo"})
|
|
119
|
+
const semanticMismatches = verification.discrepancies.filter((d) => this.isSemanticMismatch(d));
|
|
120
|
+
result.discrepancies.push(...semanticMismatches);
|
|
121
|
+
}
|
|
122
|
+
// Log discrepancies
|
|
123
|
+
if (result.discrepancies.length > 0) {
|
|
124
|
+
result.warnings.push(...result.discrepancies.map((d) => `Field persistence issue: ${d}`));
|
|
125
|
+
logError('FieldPersistenceHandler', `Field persistence warnings for ${resourceType} ${recordId}:`, result.warnings);
|
|
126
|
+
}
|
|
127
|
+
// Throw in strict mode if semantic mismatches exist
|
|
128
|
+
if (isStrictMode && result.discrepancies.length > 0) {
|
|
129
|
+
logError('FieldPersistenceHandler', 'Field persistence verification failed (strict mode)', new Error('Verification failed'), {
|
|
130
|
+
resourceType,
|
|
131
|
+
recordId,
|
|
132
|
+
discrepancies: result.discrepancies,
|
|
133
|
+
});
|
|
134
|
+
throw new UniversalValidationError(`Field persistence verification failed: ${result.discrepancies.join('; ')}`, ErrorType.API_ERROR, {
|
|
135
|
+
field: 'field_verification',
|
|
136
|
+
suggestion: 'Check that field values are correctly formatted and supported by the API',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
debug('FieldPersistenceHandler', 'Verification passed', {
|
|
142
|
+
resourceType,
|
|
143
|
+
recordId,
|
|
144
|
+
fieldCount: Object.keys(expectedData).length,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
// Catch verification errors (network, API errors, etc.)
|
|
150
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
151
|
+
result.warnings.push(`Field verification warning: ${errorMessage}`);
|
|
152
|
+
logError('FieldPersistenceHandler', 'Field persistence verification error', error);
|
|
153
|
+
// Re-throw validation errors (strict mode failures)
|
|
154
|
+
if (error instanceof UniversalValidationError) {
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Determine if a discrepancy is semantic (real) vs cosmetic (format-only)
|
|
162
|
+
*
|
|
163
|
+
* Cosmetic mismatches occur when the same logical value is represented differently:
|
|
164
|
+
* - String vs object: "Demo" vs {title: "Demo"}
|
|
165
|
+
* - Array wrapping: "value" vs ["value"]
|
|
166
|
+
* - Type coercion: "123" vs 123
|
|
167
|
+
*
|
|
168
|
+
* Semantic mismatches indicate actual data loss or corruption:
|
|
169
|
+
* - Different values: "Demo" vs "Qualified"
|
|
170
|
+
* - Missing data: {field: "value"} vs {}
|
|
171
|
+
*
|
|
172
|
+
* @param discrepancy - Discrepancy message from verification
|
|
173
|
+
* @returns true if semantic mismatch, false if cosmetic
|
|
174
|
+
*/
|
|
175
|
+
static isSemanticMismatch(discrepancy) {
|
|
176
|
+
// Extract expected and actual from: Field "X" persistence mismatch: expected Y, got Z
|
|
177
|
+
const match = discrepancy.match(/expected (.+?), got (.+?)$/);
|
|
178
|
+
if (!match) {
|
|
179
|
+
// If we can't parse, assume semantic (log for safety)
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
const [, expectedStr, actualStr] = match;
|
|
183
|
+
try {
|
|
184
|
+
// Check for cosmetic mismatches
|
|
185
|
+
// Case 1: String value vs object with title property
|
|
186
|
+
const isCosmetic = (expectedStr.includes('"') &&
|
|
187
|
+
actualStr.includes(expectedStr.replace(/^"|"$/g, ''))) ||
|
|
188
|
+
(actualStr.includes('"') &&
|
|
189
|
+
expectedStr.includes(actualStr.replace(/^"|"$/g, '')));
|
|
190
|
+
return !isCosmetic; // Return true for semantic, false for cosmetic
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// On parse errors, assume semantic (safety)
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=FieldPersistenceHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldPersistenceHandler.js","sourceRoot":"","sources":["../../../src/services/update/FieldPersistenceHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FieldValidationHandler - Validation orchestration with display name resolution
|
|
3
|
+
*
|
|
4
|
+
* Consolidates validation logic and integrates display name resolution
|
|
5
|
+
* for create/update operations.
|
|
6
|
+
*
|
|
7
|
+
* @see Issue #984 - Extend display name resolution to create/update operations
|
|
8
|
+
*/
|
|
9
|
+
import { UniversalResourceType } from '../../handlers/tool-configs/universal/types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Result of field validation
|
|
12
|
+
*/
|
|
13
|
+
export interface ValidationResult {
|
|
14
|
+
/** Whether validation passed */
|
|
15
|
+
valid: boolean;
|
|
16
|
+
/** Validation errors (blocking) */
|
|
17
|
+
errors: string[];
|
|
18
|
+
/** Validation warnings (non-blocking) */
|
|
19
|
+
warnings: string[];
|
|
20
|
+
/** Field suggestions for user */
|
|
21
|
+
suggestions: string[];
|
|
22
|
+
/** Map of display name → API slug resolutions */
|
|
23
|
+
resolvedFields?: Map<string, string>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* FieldValidationHandler - Validation and display name resolution
|
|
27
|
+
*/
|
|
28
|
+
export declare class FieldValidationHandler {
|
|
29
|
+
/**
|
|
30
|
+
* Validate fields and optionally resolve display names to API slugs
|
|
31
|
+
*
|
|
32
|
+
* Integrates display name resolution (previously only in get_attribute_options)
|
|
33
|
+
* to work for create/update operations.
|
|
34
|
+
*
|
|
35
|
+
* @param resourceType - Resource type being validated
|
|
36
|
+
* @param values - Field values to validate
|
|
37
|
+
* @param objectSlug - Optional object slug for display name resolution
|
|
38
|
+
* @param enableDisplayNameResolution - Whether to attempt display name resolution (default: true)
|
|
39
|
+
* @returns Validation result with warnings, suggestions, and resolved field names
|
|
40
|
+
*/
|
|
41
|
+
static validateAndResolve(resourceType: UniversalResourceType, values: Record<string, unknown>, objectSlug?: string, enableDisplayNameResolution?: boolean): Promise<ValidationResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Apply deal-specific validation and defaults
|
|
44
|
+
*
|
|
45
|
+
* @param values - Deal values to validate
|
|
46
|
+
* @param skipApiValidation - Whether to skip API validation
|
|
47
|
+
* @returns Deal validation result with validated data, warnings, and suggestions
|
|
48
|
+
*/
|
|
49
|
+
static validateDealDefaults(values: Record<string, unknown>, skipApiValidation?: boolean): Promise<{
|
|
50
|
+
dealData: Record<string, unknown>;
|
|
51
|
+
warnings: string[];
|
|
52
|
+
suggestions: string[];
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Attempt to resolve display names to API slugs for unknown fields
|
|
56
|
+
*
|
|
57
|
+
* This extends display name resolution (previously only in get_attribute_options)
|
|
58
|
+
* to work for create/update operations, improving UX consistency.
|
|
59
|
+
*
|
|
60
|
+
* @param values - Field values (may contain display names like "Deal stage")
|
|
61
|
+
* @param objectSlug - Object slug for attribute lookup
|
|
62
|
+
* @param result - Validation result to populate with resolutions
|
|
63
|
+
*/
|
|
64
|
+
private static resolveDisplayNames;
|
|
65
|
+
/**
|
|
66
|
+
* Attempt to resolve a display name to an API slug
|
|
67
|
+
*
|
|
68
|
+
* Uses the exported resolveAttributeDisplayName from shared-handlers.ts
|
|
69
|
+
* to support user-friendly field names like "Deal stage" instead of "stage"
|
|
70
|
+
*
|
|
71
|
+
* @param objectSlug - The object slug (e.g., "deals", "companies")
|
|
72
|
+
* @param fieldName - The field name to resolve (e.g., "Deal stage")
|
|
73
|
+
* @returns The resolved API slug if found, or null
|
|
74
|
+
*/
|
|
75
|
+
private static attemptDisplayNameResolution;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=FieldValidationHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldValidationHandler.d.ts","sourceRoot":"","sources":["../../../src/services/update/FieldValidationHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAKnF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,mCAAmC;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iCAAiC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iDAAiD;IACjD,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,sBAAsB;IACjC;;;;;;;;;;;OAWG;WACU,kBAAkB,CAC7B,YAAY,EAAE,qBAAqB,EACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,UAAU,CAAC,EAAE,MAAM,EACnB,2BAA2B,GAAE,OAAc,GAC1C,OAAO,CAAC,gBAAgB,CAAC;IA2C5B;;;;;;OAMG;WACU,oBAAoB,CAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,iBAAiB,GAAE,OAAe,GACjC,OAAO,CAAC;QACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IAqCF;;;;;;;;;OASG;mBACkB,mBAAmB;IA2CxC;;;;;;;;;OASG;mBACkB,4BAA4B;CAoBlD"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FieldValidationHandler - Validation orchestration with display name resolution
|
|
3
|
+
*
|
|
4
|
+
* Consolidates validation logic and integrates display name resolution
|
|
5
|
+
* for create/update operations.
|
|
6
|
+
*
|
|
7
|
+
* @see Issue #984 - Extend display name resolution to create/update operations
|
|
8
|
+
*/
|
|
9
|
+
import { validateFields } from '../../handlers/tool-configs/universal/field-mapper.js';
|
|
10
|
+
import { ValidationService } from '../../services/ValidationService.js';
|
|
11
|
+
import { debug, OperationType } from '../../utils/logger.js';
|
|
12
|
+
/**
|
|
13
|
+
* FieldValidationHandler - Validation and display name resolution
|
|
14
|
+
*/
|
|
15
|
+
export class FieldValidationHandler {
|
|
16
|
+
/**
|
|
17
|
+
* Validate fields and optionally resolve display names to API slugs
|
|
18
|
+
*
|
|
19
|
+
* Integrates display name resolution (previously only in get_attribute_options)
|
|
20
|
+
* to work for create/update operations.
|
|
21
|
+
*
|
|
22
|
+
* @param resourceType - Resource type being validated
|
|
23
|
+
* @param values - Field values to validate
|
|
24
|
+
* @param objectSlug - Optional object slug for display name resolution
|
|
25
|
+
* @param enableDisplayNameResolution - Whether to attempt display name resolution (default: true)
|
|
26
|
+
* @returns Validation result with warnings, suggestions, and resolved field names
|
|
27
|
+
*/
|
|
28
|
+
static async validateAndResolve(resourceType, values, objectSlug, enableDisplayNameResolution = true) {
|
|
29
|
+
const result = {
|
|
30
|
+
valid: true,
|
|
31
|
+
errors: [],
|
|
32
|
+
warnings: [],
|
|
33
|
+
suggestions: [],
|
|
34
|
+
resolvedFields: new Map(),
|
|
35
|
+
};
|
|
36
|
+
// Pre-validate fields with suggestions
|
|
37
|
+
const fieldValidation = validateFields(resourceType, values);
|
|
38
|
+
// Propagate validation results (PR #1006 Phase 3.1)
|
|
39
|
+
result.valid = fieldValidation.valid;
|
|
40
|
+
result.errors.push(...fieldValidation.errors);
|
|
41
|
+
if (fieldValidation.warnings.length > 0) {
|
|
42
|
+
result.warnings.push(...fieldValidation.warnings);
|
|
43
|
+
debug('FieldValidationHandler', 'Field validation warnings', {
|
|
44
|
+
resourceType,
|
|
45
|
+
warnings: fieldValidation.warnings.join('\n'),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (fieldValidation.suggestions.length > 0) {
|
|
49
|
+
const truncated = ValidationService.truncateSuggestions(fieldValidation.suggestions);
|
|
50
|
+
result.suggestions.push(...truncated);
|
|
51
|
+
debug('FieldValidationHandler', 'Field suggestions', {
|
|
52
|
+
resourceType,
|
|
53
|
+
suggestions: truncated.join('\n'),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// NEW: Attempt display name resolution for unknown fields
|
|
57
|
+
if (enableDisplayNameResolution && objectSlug) {
|
|
58
|
+
await this.resolveDisplayNames(values, objectSlug, result);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Apply deal-specific validation and defaults
|
|
64
|
+
*
|
|
65
|
+
* @param values - Deal values to validate
|
|
66
|
+
* @param skipApiValidation - Whether to skip API validation
|
|
67
|
+
* @returns Deal validation result with validated data, warnings, and suggestions
|
|
68
|
+
*/
|
|
69
|
+
static async validateDealDefaults(values, skipApiValidation = false) {
|
|
70
|
+
try {
|
|
71
|
+
const { applyDealDefaultsWithValidation } = await import('../../config/deal-defaults.js');
|
|
72
|
+
const dealValidation = await applyDealDefaultsWithValidation(values, skipApiValidation);
|
|
73
|
+
debug('FieldValidationHandler', 'Deal validation applied', {
|
|
74
|
+
warnings: dealValidation.warnings,
|
|
75
|
+
suggestions: dealValidation.suggestions,
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
dealData: dealValidation.dealData,
|
|
79
|
+
warnings: dealValidation.warnings,
|
|
80
|
+
suggestions: dealValidation.suggestions,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
85
|
+
debug('FieldValidationHandler', 'Deal validation failed', {
|
|
86
|
+
error: errorMessage,
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
dealData: values,
|
|
90
|
+
warnings: [`Deal validation warning: ${errorMessage}`],
|
|
91
|
+
suggestions: [],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Attempt to resolve display names to API slugs for unknown fields
|
|
97
|
+
*
|
|
98
|
+
* This extends display name resolution (previously only in get_attribute_options)
|
|
99
|
+
* to work for create/update operations, improving UX consistency.
|
|
100
|
+
*
|
|
101
|
+
* @param values - Field values (may contain display names like "Deal stage")
|
|
102
|
+
* @param objectSlug - Object slug for attribute lookup
|
|
103
|
+
* @param result - Validation result to populate with resolutions
|
|
104
|
+
*/
|
|
105
|
+
static async resolveDisplayNames(values, objectSlug, result) {
|
|
106
|
+
// Import display name resolver (will be exported in Phase 4)
|
|
107
|
+
// For now, we'll use a simplified version until shared-handlers exports it
|
|
108
|
+
try {
|
|
109
|
+
const fieldNames = Object.keys(values);
|
|
110
|
+
for (const fieldName of fieldNames) {
|
|
111
|
+
// Only attempt resolution for fields with spaces or mixed case (likely display names)
|
|
112
|
+
const mightBeDisplayName = fieldName.includes(' ') || /[A-Z]/.test(fieldName);
|
|
113
|
+
if (!mightBeDisplayName) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
// Attempt to resolve display name to API slug
|
|
117
|
+
// Uses the exported resolveAttributeDisplayName from shared-handlers.ts
|
|
118
|
+
const resolved = await this.attemptDisplayNameResolution(objectSlug, fieldName);
|
|
119
|
+
if (resolved && resolved !== fieldName) {
|
|
120
|
+
result.resolvedFields.set(fieldName, resolved);
|
|
121
|
+
debug('FieldValidationHandler', 'Resolved display name', {
|
|
122
|
+
from: fieldName,
|
|
123
|
+
to: resolved,
|
|
124
|
+
objectSlug,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
// Silent fallback - display name resolution is best-effort
|
|
131
|
+
debug('FieldValidationHandler', 'Display name resolution failed', {
|
|
132
|
+
error: error instanceof Error ? error.message : String(error),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Attempt to resolve a display name to an API slug
|
|
138
|
+
*
|
|
139
|
+
* Uses the exported resolveAttributeDisplayName from shared-handlers.ts
|
|
140
|
+
* to support user-friendly field names like "Deal stage" instead of "stage"
|
|
141
|
+
*
|
|
142
|
+
* @param objectSlug - The object slug (e.g., "deals", "companies")
|
|
143
|
+
* @param fieldName - The field name to resolve (e.g., "Deal stage")
|
|
144
|
+
* @returns The resolved API slug if found, or null
|
|
145
|
+
*/
|
|
146
|
+
static async attemptDisplayNameResolution(objectSlug, fieldName) {
|
|
147
|
+
try {
|
|
148
|
+
const { resolveAttributeDisplayName } = await import('../../handlers/tool-configs/universal/shared-handlers.js');
|
|
149
|
+
return await resolveAttributeDisplayName(objectSlug, fieldName);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
debug('FieldValidationHandler', 'Display name resolution failed', { objectSlug, fieldName, error: err }, 'attemptDisplayNameResolution', OperationType.DATA_PROCESSING);
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=FieldValidationHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldValidationHandler.js","sourceRoot":"","sources":["../../../src/services/update/FieldValidationHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataResolver - Centralized metadata fetching with caching
|
|
3
|
+
*
|
|
4
|
+
* Consolidates duplicate metadata fetching from UniversalUpdateService
|
|
5
|
+
* and value-transformer into a single, cacheable operation.
|
|
6
|
+
*
|
|
7
|
+
* @see Issue #984 - Consolidate metadata fetching to reduce API calls by 40-60%
|
|
8
|
+
*/
|
|
9
|
+
import { UniversalResourceType } from '../../handlers/tool-configs/universal/types.js';
|
|
10
|
+
import type { AttributeMetadata } from '../../services/value-transformer/types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Result of metadata resolution
|
|
13
|
+
*/
|
|
14
|
+
export interface MetadataResolutionResult {
|
|
15
|
+
/** Map of attribute slug → metadata for transformer */
|
|
16
|
+
metadataMap: Map<string, AttributeMetadata>;
|
|
17
|
+
/** Array of attribute slugs (lowercase) for field mapper */
|
|
18
|
+
availableAttributes: string[];
|
|
19
|
+
/** Whether result came from cache (true) or fresh fetch (false) */
|
|
20
|
+
fromCache: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* MetadataResolver - Single source of truth for metadata fetching
|
|
24
|
+
*/
|
|
25
|
+
export declare class MetadataResolver {
|
|
26
|
+
/**
|
|
27
|
+
* Fetch metadata for a resource type with caching
|
|
28
|
+
*
|
|
29
|
+
* This is the single entry point for metadata fetching across
|
|
30
|
+
* UniversalUpdateService, UniversalCreateService, and value-transformer.
|
|
31
|
+
*
|
|
32
|
+
* @param resourceType - The resource type to fetch metadata for
|
|
33
|
+
* @param recordData - Optional record data containing object slug
|
|
34
|
+
* @returns Metadata map and available attributes for field mapping
|
|
35
|
+
*/
|
|
36
|
+
static fetchMetadata(resourceType: UniversalResourceType, recordData?: Record<string, unknown>): Promise<MetadataResolutionResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Fetch fresh metadata from Attio API
|
|
39
|
+
*/
|
|
40
|
+
private static fetchFreshMetadata;
|
|
41
|
+
/**
|
|
42
|
+
* Extract object slug from resource type and record data
|
|
43
|
+
*/
|
|
44
|
+
static extractObjectSlug(resourceType: UniversalResourceType, recordData?: Record<string, unknown>): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Extract attribute slugs for field mapper (lowercase)
|
|
47
|
+
*/
|
|
48
|
+
private static extractAttributeSlugs;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=MetadataResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetadataResolver.d.ts","sourceRoot":"","sources":["../../../src/services/update/MetadataResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAGnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAI/E;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uDAAuD;IACvD,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC5C,4DAA4D;IAC5D,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,mEAAmE;IACnE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;;;;;;;;OASG;WACU,aAAa,CACxB,YAAY,EAAE,qBAAqB,EACnC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,wBAAwB,CAAC;IAkFpC;;OAEG;mBACkB,kBAAkB;IAevC;;OAEG;WACW,iBAAiB,CAC7B,YAAY,EAAE,qBAAqB,EACnC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,GAAG,SAAS;IAcrB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;CAarC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataResolver - Centralized metadata fetching with caching
|
|
3
|
+
*
|
|
4
|
+
* Consolidates duplicate metadata fetching from UniversalUpdateService
|
|
5
|
+
* and value-transformer into a single, cacheable operation.
|
|
6
|
+
*
|
|
7
|
+
* @see Issue #984 - Consolidate metadata fetching to reduce API calls by 40-60%
|
|
8
|
+
*/
|
|
9
|
+
import { UniversalResourceType } from '../../handlers/tool-configs/universal/types.js';
|
|
10
|
+
import { CachingService } from '../../services/CachingService.js';
|
|
11
|
+
import { DEFAULT_ATTRIBUTES_CACHE_TTL } from '../../constants/universal.constants.js';
|
|
12
|
+
import { debug, error as logError } from '../../utils/logger.js';
|
|
13
|
+
import { convertToMetadataMap } from '../../utils/metadata-utils.js';
|
|
14
|
+
/**
|
|
15
|
+
* MetadataResolver - Single source of truth for metadata fetching
|
|
16
|
+
*/
|
|
17
|
+
export class MetadataResolver {
|
|
18
|
+
/**
|
|
19
|
+
* Fetch metadata for a resource type with caching
|
|
20
|
+
*
|
|
21
|
+
* This is the single entry point for metadata fetching across
|
|
22
|
+
* UniversalUpdateService, UniversalCreateService, and value-transformer.
|
|
23
|
+
*
|
|
24
|
+
* @param resourceType - The resource type to fetch metadata for
|
|
25
|
+
* @param recordData - Optional record data containing object slug
|
|
26
|
+
* @returns Metadata map and available attributes for field mapping
|
|
27
|
+
*/
|
|
28
|
+
static async fetchMetadata(resourceType, recordData) {
|
|
29
|
+
const objectSlug = this.extractObjectSlug(resourceType, recordData);
|
|
30
|
+
try {
|
|
31
|
+
// Try cache first, then load fresh data
|
|
32
|
+
const result = await CachingService.getOrLoadAttributes(() => this.fetchFreshMetadata(resourceType, objectSlug), resourceType, objectSlug, DEFAULT_ATTRIBUTES_CACHE_TTL);
|
|
33
|
+
// Use shared utility from metadata-utils (PR #1006 Phase 2.1)
|
|
34
|
+
const metadataMap = convertToMetadataMap(result.data);
|
|
35
|
+
const availableAttributes = this.extractAttributeSlugs(metadataMap);
|
|
36
|
+
debug('MetadataResolver', 'Metadata fetched', {
|
|
37
|
+
resourceType,
|
|
38
|
+
objectSlug,
|
|
39
|
+
fromCache: result.fromCache,
|
|
40
|
+
attributeCount: metadataMap.size,
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
metadataMap,
|
|
44
|
+
availableAttributes,
|
|
45
|
+
fromCache: result.fromCache,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
50
|
+
// Re-throw critical authentication errors (Issue #984 extension - PR review feedback)
|
|
51
|
+
if (error.message.includes('401') ||
|
|
52
|
+
error.message.includes('403') ||
|
|
53
|
+
error.message.includes('Unauthorized') ||
|
|
54
|
+
error.message.includes('Forbidden')) {
|
|
55
|
+
logError('MetadataResolver', 'Authentication error fetching metadata', error, { resourceType, objectSlug });
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
// Re-throw schema validation errors
|
|
59
|
+
if (error.message.includes('validation') ||
|
|
60
|
+
error.message.includes('schema')) {
|
|
61
|
+
logError('MetadataResolver', 'Schema validation error fetching metadata', error, { resourceType, objectSlug });
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
// Log and return empty for non-critical errors (transient failures, network issues)
|
|
65
|
+
logError('MetadataResolver', 'Non-critical metadata fetch error, using empty metadata', error, { resourceType, objectSlug });
|
|
66
|
+
debug('MetadataResolver', 'Graceful degradation with empty metadata', {
|
|
67
|
+
resourceType,
|
|
68
|
+
objectSlug,
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
metadataMap: new Map(),
|
|
72
|
+
availableAttributes: [],
|
|
73
|
+
fromCache: false,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Fetch fresh metadata from Attio API
|
|
79
|
+
*/
|
|
80
|
+
static async fetchFreshMetadata(resourceType, objectSlug) {
|
|
81
|
+
const { UniversalMetadataService } = await import('../../services/UniversalMetadataService.js');
|
|
82
|
+
const options = objectSlug ? { objectSlug } : undefined;
|
|
83
|
+
return UniversalMetadataService.discoverAttributesForResourceType(resourceType, options);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Extract object slug from resource type and record data
|
|
87
|
+
*/
|
|
88
|
+
static extractObjectSlug(resourceType, recordData) {
|
|
89
|
+
if (resourceType === UniversalResourceType.RECORDS) {
|
|
90
|
+
return (recordData?.object ||
|
|
91
|
+
recordData?.object_api_slug ||
|
|
92
|
+
'records');
|
|
93
|
+
}
|
|
94
|
+
if (resourceType === UniversalResourceType.DEALS) {
|
|
95
|
+
return 'deals';
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extract attribute slugs for field mapper (lowercase)
|
|
101
|
+
*/
|
|
102
|
+
static extractAttributeSlugs(metadataMap) {
|
|
103
|
+
return Array.from(new Set(Array.from(metadataMap.values()).flatMap((attr) => {
|
|
104
|
+
return [attr.api_slug, attr.title, attr.slug]
|
|
105
|
+
.filter((s) => typeof s === 'string')
|
|
106
|
+
.map((s) => s.toLowerCase());
|
|
107
|
+
})));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=MetadataResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetadataResolver.js","sourceRoot":"","sources":["../../../src/services/update/MetadataResolver.ts"],"names":[],"mappings":"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"}
|