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
package/dist/handlers/tool-configs/universal/core/error-enhancers/record-reference-enhancer.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record Reference Error Enhancer
|
|
3
|
+
* Issue #1001 - Strategy Pattern for CRUD error handling
|
|
4
|
+
* Issue #997 - Enhanced record-reference attribute error handling
|
|
5
|
+
*
|
|
6
|
+
* Detects "Missing target_object on record reference value" and similar errors
|
|
7
|
+
* Provides format guidance for record-reference fields.
|
|
8
|
+
*/
|
|
9
|
+
import { getErrorMessage, isAxiosError } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Enhance error messages for record-reference attribute errors
|
|
12
|
+
*/
|
|
13
|
+
const enhanceRecordReferenceError = (error, recordData) => {
|
|
14
|
+
const msg = getErrorMessage(error);
|
|
15
|
+
// Also check for validation_errors in axios response
|
|
16
|
+
let fullErrorText = msg;
|
|
17
|
+
if (isAxiosError(error)) {
|
|
18
|
+
const data = error.response?.data;
|
|
19
|
+
if (data?.message) {
|
|
20
|
+
fullErrorText += ' ' + data.message;
|
|
21
|
+
}
|
|
22
|
+
if (data?.validation_errors) {
|
|
23
|
+
fullErrorText +=
|
|
24
|
+
' ' +
|
|
25
|
+
data.validation_errors.map((e) => String(e.message || e)).join(' ');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Pattern detection for record-reference errors
|
|
29
|
+
const isRecordRefError = fullErrorText.includes('Missing target_object') ||
|
|
30
|
+
fullErrorText.includes('record reference') ||
|
|
31
|
+
fullErrorText.includes('target_record_id') ||
|
|
32
|
+
(fullErrorText.includes('Invalid value was passed to attribute') &&
|
|
33
|
+
(fullErrorText.includes('company') ||
|
|
34
|
+
fullErrorText.includes('associated_people') ||
|
|
35
|
+
fullErrorText.includes('associated_company') ||
|
|
36
|
+
fullErrorText.includes('main_contact')));
|
|
37
|
+
if (!isRecordRefError)
|
|
38
|
+
return null;
|
|
39
|
+
// Try to identify which field might be the issue
|
|
40
|
+
const potentialRefFields = [
|
|
41
|
+
'company',
|
|
42
|
+
'associated_company',
|
|
43
|
+
'associated_people',
|
|
44
|
+
'main_contact',
|
|
45
|
+
'person',
|
|
46
|
+
'people',
|
|
47
|
+
];
|
|
48
|
+
let affectedField = null;
|
|
49
|
+
if (recordData) {
|
|
50
|
+
for (const field of potentialRefFields) {
|
|
51
|
+
if (field in recordData) {
|
|
52
|
+
affectedField = field;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
let message = `Record reference format error`;
|
|
58
|
+
if (affectedField) {
|
|
59
|
+
message += ` on field "${affectedField}"`;
|
|
60
|
+
}
|
|
61
|
+
message += `.\n\n`;
|
|
62
|
+
message += `The Attio API expects record-reference fields in this format:\n`;
|
|
63
|
+
message += ` [{ "target_object": "object_type", "target_record_id": "uuid" }]\n\n`;
|
|
64
|
+
message += `Simplified formats (auto-transformed by this server):\n`;
|
|
65
|
+
message += ` • String: "company": "record-uuid"\n`;
|
|
66
|
+
message += ` • Legacy object: "company": {"record_id": "uuid"}\n\n`;
|
|
67
|
+
message += `If you're seeing this error, the auto-transformation may have failed.\n`;
|
|
68
|
+
message += `Ensure the record ID is valid and the field name is correct.`;
|
|
69
|
+
return message;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Record Reference Enhancer
|
|
73
|
+
* Handles record-reference field format errors (Issue #997)
|
|
74
|
+
*/
|
|
75
|
+
export const recordReferenceEnhancer = {
|
|
76
|
+
name: 'record-reference',
|
|
77
|
+
errorName: 'record_reference_error',
|
|
78
|
+
matches: (error, _context) => {
|
|
79
|
+
const msg = getErrorMessage(error);
|
|
80
|
+
// Check for axios validation errors
|
|
81
|
+
let fullText = msg;
|
|
82
|
+
if (isAxiosError(error)) {
|
|
83
|
+
const data = error.response?.data;
|
|
84
|
+
if (data?.message) {
|
|
85
|
+
fullText += ' ' + data.message;
|
|
86
|
+
}
|
|
87
|
+
// CRITICAL: Also check validation_errors array for record-reference patterns
|
|
88
|
+
if (data?.validation_errors) {
|
|
89
|
+
fullText +=
|
|
90
|
+
' ' +
|
|
91
|
+
data.validation_errors.map((e) => String(e.message || e)).join(' ');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return (fullText.includes('Missing target_object') ||
|
|
95
|
+
fullText.includes('record reference') ||
|
|
96
|
+
fullText.includes('target_record_id') ||
|
|
97
|
+
// CRITICAL: Match "Invalid value was passed to attribute" pattern (from enhanceRecordReferenceError)
|
|
98
|
+
(fullText.includes('Invalid value was passed to attribute') &&
|
|
99
|
+
(fullText.includes('company') ||
|
|
100
|
+
fullText.includes('associated_people') ||
|
|
101
|
+
fullText.includes('associated_company') ||
|
|
102
|
+
fullText.includes('main_contact'))));
|
|
103
|
+
},
|
|
104
|
+
enhance: async (error, context) => {
|
|
105
|
+
return enhanceRecordReferenceError(error, context.recordData);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=record-reference-enhancer.js.map
|
package/dist/handlers/tool-configs/universal/core/error-enhancers/record-reference-enhancer.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-reference-enhancer.js","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/record-reference-enhancer.ts"],"names":[],"mappings":"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"}
|
package/dist/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Required Fields Error Enhancer
|
|
3
|
+
* Issue #1001 - Strategy Pattern for CRUD error handling
|
|
4
|
+
*
|
|
5
|
+
* Detects missing required fields and provides specific guidance,
|
|
6
|
+
* especially for deal-specific required fields like "stage".
|
|
7
|
+
*/
|
|
8
|
+
import type { ErrorEnhancer } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Required Fields Enhancer
|
|
11
|
+
* Detects missing required field errors and provides context-specific guidance
|
|
12
|
+
*/
|
|
13
|
+
export declare const requiredFieldsEnhancer: ErrorEnhancer;
|
|
14
|
+
//# sourceMappingURL=required-fields-enhancer.d.ts.map
|
package/dist/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"required-fields-enhancer.d.ts","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAwFlE;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,aA0BpC,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Required Fields Error Enhancer
|
|
3
|
+
* Issue #1001 - Strategy Pattern for CRUD error handling
|
|
4
|
+
*
|
|
5
|
+
* Detects missing required fields and provides specific guidance,
|
|
6
|
+
* especially for deal-specific required fields like "stage".
|
|
7
|
+
*/
|
|
8
|
+
import { UniversalResourceType } from '../../../../../handlers/tool-configs/universal/types.js';
|
|
9
|
+
import { sanitizedLog } from '../pii-sanitizer.js';
|
|
10
|
+
import { createScopedLogger } from '../../../../../utils/logger.js';
|
|
11
|
+
const logger = createScopedLogger('required-fields-enhancer');
|
|
12
|
+
/**
|
|
13
|
+
* Normalize field names for comparison
|
|
14
|
+
*/
|
|
15
|
+
const normalizeFieldName = (field) => field.trim().toLowerCase();
|
|
16
|
+
/**
|
|
17
|
+
* Check if recordData contains a stage field (for deals)
|
|
18
|
+
*/
|
|
19
|
+
const hasStageField = (recordData) => {
|
|
20
|
+
const directKeys = Object.keys(recordData).map(normalizeFieldName);
|
|
21
|
+
if (directKeys.includes('stage') ||
|
|
22
|
+
directKeys.includes('deal stage') ||
|
|
23
|
+
directKeys.includes('status')) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
const values = recordData.values &&
|
|
27
|
+
typeof recordData.values === 'object' &&
|
|
28
|
+
recordData.values !== null
|
|
29
|
+
? recordData.values
|
|
30
|
+
: null;
|
|
31
|
+
if (!values)
|
|
32
|
+
return false;
|
|
33
|
+
const valueKeys = Object.keys(values).map(normalizeFieldName);
|
|
34
|
+
return (valueKeys.includes('stage') ||
|
|
35
|
+
valueKeys.includes('deal stage') ||
|
|
36
|
+
valueKeys.includes('status'));
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Build enhanced error message for missing deal stage
|
|
40
|
+
*/
|
|
41
|
+
const buildMissingDealStageMessage = async (recordData) => {
|
|
42
|
+
if (hasStageField(recordData))
|
|
43
|
+
return null;
|
|
44
|
+
try {
|
|
45
|
+
const { AttributeOptionsService } = await import('../../../../../services/metadata/index.js');
|
|
46
|
+
const { options } = await AttributeOptionsService.getOptions('deals', 'stage');
|
|
47
|
+
const preview = options
|
|
48
|
+
.slice(0, 5)
|
|
49
|
+
.map((option) => `"${option.title}"`)
|
|
50
|
+
.join(', ');
|
|
51
|
+
const hasMore = options.length > 5 ? ` (+${options.length - 5} more)` : '';
|
|
52
|
+
return (`Required field "stage" is missing for deals.\n\n` +
|
|
53
|
+
`Common stage values: ${preview}${hasMore}\n\n` +
|
|
54
|
+
`For the full list, call: records_get_attribute_options(resource_type="deals", attribute="stage").`);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
sanitizedLog(logger, 'debug', 'Failed to fetch stage options for enhanced error message', {
|
|
58
|
+
enhancerName: 'required-fields',
|
|
59
|
+
resourceType: 'deals',
|
|
60
|
+
attribute: 'stage',
|
|
61
|
+
error: err instanceof Error ? err.message : String(err),
|
|
62
|
+
});
|
|
63
|
+
return (`Required field "stage" is missing for deals.\n\n` +
|
|
64
|
+
`Call records_get_attribute_options(resource_type="deals", attribute="stage") to retrieve valid stage values, then retry.`);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Required Fields Enhancer
|
|
69
|
+
* Detects missing required field errors and provides context-specific guidance
|
|
70
|
+
*/
|
|
71
|
+
export const requiredFieldsEnhancer = {
|
|
72
|
+
name: 'required-fields',
|
|
73
|
+
errorName: 'validation_error',
|
|
74
|
+
matches: (error, _context) => {
|
|
75
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
76
|
+
return msg.includes('required field') || msg.includes('Missing required');
|
|
77
|
+
},
|
|
78
|
+
enhance: async (_error, context) => {
|
|
79
|
+
const { resourceType, recordData } = context;
|
|
80
|
+
// Deal-specific required field handling
|
|
81
|
+
if (resourceType === UniversalResourceType.DEALS && recordData) {
|
|
82
|
+
const stageMessage = await buildMissingDealStageMessage(recordData);
|
|
83
|
+
if (stageMessage) {
|
|
84
|
+
return stageMessage;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Generic required field message
|
|
88
|
+
return 'Missing required fields. Please check that all mandatory fields are provided.';
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=required-fields-enhancer.js.map
|
package/dist/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"required-fields-enhancer.js","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/required-fields-enhancer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Select/Status Error Enhancer
|
|
3
|
+
* Issue #1001 - Strategy Pattern for CRUD error handling
|
|
4
|
+
*
|
|
5
|
+
* Detects "Cannot find select option" or "Cannot find Status" errors
|
|
6
|
+
* and provides valid options from AttributeOptionsService.
|
|
7
|
+
*/
|
|
8
|
+
import type { ErrorEnhancer } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Select/Status Enhancer
|
|
11
|
+
* Provides valid options for select and status field errors
|
|
12
|
+
*/
|
|
13
|
+
export declare const selectStatusEnhancer: ErrorEnhancer;
|
|
14
|
+
//# sourceMappingURL=select-status-enhancer.d.ts.map
|
package/dist/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-status-enhancer.d.ts","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAqIlE;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAqBlC,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Select/Status Error Enhancer
|
|
3
|
+
* Issue #1001 - Strategy Pattern for CRUD error handling
|
|
4
|
+
*
|
|
5
|
+
* Detects "Cannot find select option" or "Cannot find Status" errors
|
|
6
|
+
* and provides valid options from AttributeOptionsService.
|
|
7
|
+
*/
|
|
8
|
+
import { getErrorMessage, isAxiosError } from './types.js';
|
|
9
|
+
import { sanitizedLog } from '../pii-sanitizer.js';
|
|
10
|
+
import { createScopedLogger } from '../../../../../utils/logger.js';
|
|
11
|
+
const logger = createScopedLogger('select-status-enhancer');
|
|
12
|
+
/**
|
|
13
|
+
* Enhance error messages for select/status attribute errors
|
|
14
|
+
*/
|
|
15
|
+
const enhanceSelectStatusError = async (error, resourceType, recordData) => {
|
|
16
|
+
const msg = getErrorMessage(error);
|
|
17
|
+
// Attempt to extract validation_errors array for better detail on select fields
|
|
18
|
+
if (isAxiosError(error)) {
|
|
19
|
+
const validationErrors = error.response?.data?.validation_errors;
|
|
20
|
+
if (validationErrors) {
|
|
21
|
+
const selectErr = validationErrors.find((ve) => String(ve?.message || '').includes('select option'));
|
|
22
|
+
if (selectErr?.field) {
|
|
23
|
+
try {
|
|
24
|
+
const { AttributeOptionsService } = await import('../../../../../services/metadata/index.js');
|
|
25
|
+
const { options, attributeType } = await AttributeOptionsService.getOptions(resourceType, selectErr.field);
|
|
26
|
+
const validList = options
|
|
27
|
+
.slice(0, 8)
|
|
28
|
+
.map((o) => o.title)
|
|
29
|
+
.join(', ');
|
|
30
|
+
const hasMore = options.length > 8 ? ` (+${options.length - 8} more)` : '';
|
|
31
|
+
return `Value is not valid for ${attributeType} attribute "${selectErr.field}" on ${resourceType}.
|
|
32
|
+
Expected one of: ${validList}${hasMore}
|
|
33
|
+
|
|
34
|
+
Next step: Call records_get_attribute_options with
|
|
35
|
+
resource_type: "${resourceType}"
|
|
36
|
+
attribute: "${selectErr.field}"
|
|
37
|
+
to list all valid values, then retry.`;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
sanitizedLog(logger, 'debug', 'Failed to fetch select/status options for enhanced error message', {
|
|
41
|
+
enhancerName: 'select-status',
|
|
42
|
+
resourceType,
|
|
43
|
+
attribute: selectErr.field,
|
|
44
|
+
error: err instanceof Error ? err.message : String(err),
|
|
45
|
+
});
|
|
46
|
+
return `Value is not valid for attribute "${selectErr.field}" on ${resourceType}.
|
|
47
|
+
Next step: Call records_get_attribute_options with
|
|
48
|
+
resource_type: "${resourceType}"
|
|
49
|
+
attribute: "${selectErr.field}"
|
|
50
|
+
to see valid options, then retry.`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Pattern: "Cannot find select option with title 'X'" or "Cannot find Status with title 'X'"
|
|
56
|
+
const selectMatch = msg.match(/Cannot find (?:select option|Status) with title "(.+?)"/);
|
|
57
|
+
if (!selectMatch)
|
|
58
|
+
return null;
|
|
59
|
+
const invalidValue = selectMatch[1];
|
|
60
|
+
// Try to identify which field has the problem by checking record data
|
|
61
|
+
for (const [fieldName, fieldValue] of Object.entries(recordData)) {
|
|
62
|
+
if (fieldValue === invalidValue ||
|
|
63
|
+
(Array.isArray(fieldValue) && fieldValue.includes(invalidValue))) {
|
|
64
|
+
try {
|
|
65
|
+
const { AttributeOptionsService } = await import('../../../../../services/metadata/index.js');
|
|
66
|
+
const { options, attributeType } = await AttributeOptionsService.getOptions(resourceType, fieldName);
|
|
67
|
+
const validList = options
|
|
68
|
+
.slice(0, 8)
|
|
69
|
+
.map((o) => o.title)
|
|
70
|
+
.join(', ');
|
|
71
|
+
const hasMore = options.length > 8 ? ` (+${options.length - 8} more)` : '';
|
|
72
|
+
return (`Value "${invalidValue}" is not valid for ${attributeType} attribute "${fieldName}" on ${resourceType}.\n\n` +
|
|
73
|
+
`Valid options: ${validList}${hasMore}\n\n` +
|
|
74
|
+
`Next step: Call records_get_attribute_options with\n` +
|
|
75
|
+
` resource_type: "${resourceType}"\n` +
|
|
76
|
+
` attribute: "${fieldName}"\n` +
|
|
77
|
+
`to list all valid values, then retry.`);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
sanitizedLog(logger, 'debug', 'Failed to fetch attribute options (no invalid value extracted)', {
|
|
81
|
+
enhancerName: 'select-status',
|
|
82
|
+
resourceType,
|
|
83
|
+
attribute: fieldName,
|
|
84
|
+
error: err instanceof Error ? err.message : String(err),
|
|
85
|
+
});
|
|
86
|
+
return (`Value "${invalidValue}" is not valid for attribute "${fieldName}" on ${resourceType}.\n\n` +
|
|
87
|
+
`Next step: Call records_get_attribute_options with\n` +
|
|
88
|
+
` resource_type: "${resourceType}"\n` +
|
|
89
|
+
` attribute: "${fieldName}"\n` +
|
|
90
|
+
`to see valid options, then retry.`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Couldn't match to a specific field, return generic hint
|
|
95
|
+
return (`Value "${invalidValue}" is not valid for an attribute on ${resourceType}.\n\n` +
|
|
96
|
+
`Next step: Use records_get_attribute_options to discover valid options for the attribute.`);
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Select/Status Enhancer
|
|
100
|
+
* Provides valid options for select and status field errors
|
|
101
|
+
*/
|
|
102
|
+
export const selectStatusEnhancer = {
|
|
103
|
+
name: 'select-status',
|
|
104
|
+
errorName: 'value_not_found',
|
|
105
|
+
matches: (error, _context) => {
|
|
106
|
+
const msg = getErrorMessage(error);
|
|
107
|
+
return (msg.includes('Cannot find select option') ||
|
|
108
|
+
msg.includes('Cannot find Status') ||
|
|
109
|
+
msg.includes('select option'));
|
|
110
|
+
},
|
|
111
|
+
enhance: async (error, context) => {
|
|
112
|
+
const { resourceType, recordData } = context;
|
|
113
|
+
if (!recordData)
|
|
114
|
+
return null;
|
|
115
|
+
return enhanceSelectStatusError(error, resourceType, recordData);
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=select-status-enhancer.js.map
|
package/dist/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-status-enhancer.js","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/select-status-enhancer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Enhancer Strategy Pattern Types
|
|
3
|
+
* Issue #1001 - Refactoring crud-error-handlers.ts
|
|
4
|
+
*/
|
|
5
|
+
import type { ValidationMetadata } from '../../../../../handlers/tool-configs/universal/core/utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Context passed to error enhancers
|
|
8
|
+
*/
|
|
9
|
+
export interface CrudErrorContext {
|
|
10
|
+
readonly operation: 'create' | 'update' | 'delete' | 'search';
|
|
11
|
+
readonly resourceType: string;
|
|
12
|
+
readonly recordData?: Readonly<Record<string, unknown>>;
|
|
13
|
+
readonly recordId?: string;
|
|
14
|
+
readonly validationMetadata?: Readonly<ValidationMetadata>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Strategy interface for error enhancement
|
|
18
|
+
* Each enhancer implements pattern matching and message enhancement
|
|
19
|
+
*/
|
|
20
|
+
export interface ErrorEnhancer {
|
|
21
|
+
/** Unique name for the enhancer */
|
|
22
|
+
readonly name: string;
|
|
23
|
+
/** Check if this enhancer can handle the error */
|
|
24
|
+
readonly matches: (error: unknown, context: CrudErrorContext) => boolean;
|
|
25
|
+
/** Enhance the error message with context-specific details */
|
|
26
|
+
readonly enhance: (error: unknown, context: CrudErrorContext) => Promise<string | null>;
|
|
27
|
+
/** Error name to use when throwing the enhanced error */
|
|
28
|
+
readonly errorName: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Extract error message from Error instances, axios-style errors, or test mocks
|
|
32
|
+
*
|
|
33
|
+
* Handles three cases:
|
|
34
|
+
* 1. Real Error instances: returns error.message
|
|
35
|
+
* 2. Error-like objects (axios/mocks): extracts message property
|
|
36
|
+
* 3. Primitive values: converts to string
|
|
37
|
+
*
|
|
38
|
+
* This helper was added to fix test compatibility issues where test mocks
|
|
39
|
+
* aren't true Error instances but have message properties. It provides a
|
|
40
|
+
* consistent way to extract error messages across production code and tests.
|
|
41
|
+
*
|
|
42
|
+
* @param error - Any error value (Error, axios error object, string, etc.)
|
|
43
|
+
* @returns Error message as string (never null/undefined)
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* getErrorMessage(new Error("test")) // "test"
|
|
47
|
+
* getErrorMessage({ message: "axios error" }) // "axios error"
|
|
48
|
+
* getErrorMessage("string error") // "string error"
|
|
49
|
+
*/
|
|
50
|
+
export declare const getErrorMessage: (error: unknown) => string;
|
|
51
|
+
/**
|
|
52
|
+
* Axios-style error response structure
|
|
53
|
+
* Used for type-safe extraction of validation errors from Attio API responses
|
|
54
|
+
*/
|
|
55
|
+
export interface AxiosErrorResponse {
|
|
56
|
+
data?: {
|
|
57
|
+
message?: string;
|
|
58
|
+
validation_errors?: Array<{
|
|
59
|
+
field?: string;
|
|
60
|
+
path?: string;
|
|
61
|
+
message?: string;
|
|
62
|
+
}>;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Axios error with response
|
|
67
|
+
* Allows type-safe access to error.response.data.validation_errors
|
|
68
|
+
*/
|
|
69
|
+
export interface AxiosError extends Error {
|
|
70
|
+
response?: AxiosErrorResponse;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Type guard to check if error is an Axios error
|
|
74
|
+
*/
|
|
75
|
+
export declare function isAxiosError(error: unknown): error is AxiosError;
|
|
76
|
+
export type { ValidationMetadata };
|
|
77
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAE1F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC9D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;CAC5D;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC;IAEzE,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,CAChB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE5B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO,KAAG,MAMhD,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,iBAAiB,CAAC,EAAE,KAAK,CAAC;YACxB,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC,CAAC;KACJ,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,UAAW,SAAQ,KAAK;IACvC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAOhE;AAED,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Enhancer Strategy Pattern Types
|
|
3
|
+
* Issue #1001 - Refactoring crud-error-handlers.ts
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Extract error message from Error instances, axios-style errors, or test mocks
|
|
7
|
+
*
|
|
8
|
+
* Handles three cases:
|
|
9
|
+
* 1. Real Error instances: returns error.message
|
|
10
|
+
* 2. Error-like objects (axios/mocks): extracts message property
|
|
11
|
+
* 3. Primitive values: converts to string
|
|
12
|
+
*
|
|
13
|
+
* This helper was added to fix test compatibility issues where test mocks
|
|
14
|
+
* aren't true Error instances but have message properties. It provides a
|
|
15
|
+
* consistent way to extract error messages across production code and tests.
|
|
16
|
+
*
|
|
17
|
+
* @param error - Any error value (Error, axios error object, string, etc.)
|
|
18
|
+
* @returns Error message as string (never null/undefined)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* getErrorMessage(new Error("test")) // "test"
|
|
22
|
+
* getErrorMessage({ message: "axios error" }) // "axios error"
|
|
23
|
+
* getErrorMessage("string error") // "string error"
|
|
24
|
+
*/
|
|
25
|
+
export const getErrorMessage = (error) => {
|
|
26
|
+
if (error instanceof Error)
|
|
27
|
+
return error.message;
|
|
28
|
+
if (error && typeof error === 'object' && 'message' in error) {
|
|
29
|
+
return String(error.message);
|
|
30
|
+
}
|
|
31
|
+
return String(error);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Type guard to check if error is an Axios error
|
|
35
|
+
*/
|
|
36
|
+
export function isAxiosError(error) {
|
|
37
|
+
return (error !== null &&
|
|
38
|
+
typeof error === 'object' &&
|
|
39
|
+
'response' in error &&
|
|
40
|
+
typeof error.response === 'object');
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoCH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAc,EAAU,EAAE;IACxD,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACjD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAE,KAAiC,CAAC,OAAO,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC;AAyBF;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,CACL,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,UAAU,IAAI,KAAK;QACnB,OAAQ,KAAgC,CAAC,QAAQ,KAAK,QAAQ,CAC/D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uniqueness Error Enhancer
|
|
3
|
+
* Issue #1001 - Strategy Pattern for CRUD error handling
|
|
4
|
+
* Issue #990 - Enhanced uniqueness constraint violation handling
|
|
5
|
+
*
|
|
6
|
+
* Detects uniqueness/duplicate errors and attempts to find the
|
|
7
|
+
* conflicting record to provide actionable guidance.
|
|
8
|
+
*/
|
|
9
|
+
import type { ErrorEnhancer } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Uniqueness Enhancer
|
|
12
|
+
* Detects duplicate/uniqueness constraint violations and finds the conflicting record
|
|
13
|
+
*/
|
|
14
|
+
export declare const uniquenessEnhancer: ErrorEnhancer;
|
|
15
|
+
//# sourceMappingURL=uniqueness-enhancer.d.ts.map
|
package/dist/handlers/tool-configs/universal/core/error-enhancers/uniqueness-enhancer.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uniqueness-enhancer.d.ts","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/uniqueness-enhancer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAuHlE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAiChC,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uniqueness Error Enhancer
|
|
3
|
+
* Issue #1001 - Strategy Pattern for CRUD error handling
|
|
4
|
+
* Issue #990 - Enhanced uniqueness constraint violation handling
|
|
5
|
+
*
|
|
6
|
+
* Detects uniqueness/duplicate errors and attempts to find the
|
|
7
|
+
* conflicting record to provide actionable guidance.
|
|
8
|
+
*/
|
|
9
|
+
import { getSingularResourceType } from '../../../../../handlers/tool-configs/universal/shared-handlers.js';
|
|
10
|
+
import { sanitizedLog } from '../../../../../handlers/tool-configs/universal/core/pii-sanitizer.js';
|
|
11
|
+
import { createScopedLogger } from '../../../../../utils/logger.js';
|
|
12
|
+
const logger = createScopedLogger('uniqueness-enhancer');
|
|
13
|
+
/**
|
|
14
|
+
* Searches for conflicting record when uniqueness constraint violation occurs
|
|
15
|
+
*/
|
|
16
|
+
async function enhanceUniquenessErrorWithSearch(resourceType, recordData) {
|
|
17
|
+
const UNIQUE_FIELD_SEARCHERS = {
|
|
18
|
+
companies: {
|
|
19
|
+
fields: ['domains', 'domain'],
|
|
20
|
+
search: async (value) => {
|
|
21
|
+
const { searchCompaniesByDomain } = await import('../../../../../objects/companies/search.js');
|
|
22
|
+
return searchCompaniesByDomain(value);
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
people: {
|
|
26
|
+
fields: ['email_addresses', 'email', 'emails'],
|
|
27
|
+
search: async (value) => {
|
|
28
|
+
const { searchPeopleByEmail } = await import('../../../../../objects/people/search.js');
|
|
29
|
+
return searchPeopleByEmail(value);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
const searcher = UNIQUE_FIELD_SEARCHERS[resourceType.toLowerCase()];
|
|
34
|
+
if (!searcher)
|
|
35
|
+
return null;
|
|
36
|
+
// Find which unique field has a value in recordData
|
|
37
|
+
for (const field of searcher.fields) {
|
|
38
|
+
let searchValue = recordData[field];
|
|
39
|
+
// Handle array format (e.g., domains: ["example.com"])
|
|
40
|
+
if (Array.isArray(searchValue) && searchValue.length > 0) {
|
|
41
|
+
searchValue = searchValue[0];
|
|
42
|
+
}
|
|
43
|
+
// Handle object format for emails (e.g., email_addresses: [{email_address: "..."}])
|
|
44
|
+
if (searchValue &&
|
|
45
|
+
typeof searchValue === 'object' &&
|
|
46
|
+
!Array.isArray(searchValue)) {
|
|
47
|
+
const obj = searchValue;
|
|
48
|
+
searchValue = obj.email_address || obj.email || obj.value;
|
|
49
|
+
}
|
|
50
|
+
if (searchValue && typeof searchValue === 'string') {
|
|
51
|
+
try {
|
|
52
|
+
const existing = await searcher.search(searchValue);
|
|
53
|
+
if (existing && existing.length > 0) {
|
|
54
|
+
const recordId = existing[0]?.id?.record_id;
|
|
55
|
+
if (recordId) {
|
|
56
|
+
return formatUniquenessErrorMessage(resourceType, field, searchValue, recordId);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
// Search failed, log and continue to fallback
|
|
62
|
+
sanitizedLog(logger, 'debug', 'Uniqueness search failed', {
|
|
63
|
+
resourceType,
|
|
64
|
+
field,
|
|
65
|
+
error: String(err),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Formats actionable error message for uniqueness constraint violations
|
|
74
|
+
*/
|
|
75
|
+
function formatUniquenessErrorMessage(resourceType, field, value, recordId) {
|
|
76
|
+
const singular = getSingularResourceType(resourceType);
|
|
77
|
+
return (`Uniqueness conflict on "${field}": value "${value}" already exists on ${singular} record.\n\n` +
|
|
78
|
+
`EXISTING RECORD ID: ${recordId}\n\n` +
|
|
79
|
+
`OPTIONS:\n` +
|
|
80
|
+
`1. Update existing: update-record(resource_type="${resourceType}", record_id="${recordId}", record_data={...})\n` +
|
|
81
|
+
`2. View existing: records_get_details(resource_type="${resourceType}", record_id="${recordId}")\n` +
|
|
82
|
+
`3. Use a different ${field} value`);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Uniqueness Enhancer
|
|
86
|
+
* Detects duplicate/uniqueness constraint violations and finds the conflicting record
|
|
87
|
+
*/
|
|
88
|
+
export const uniquenessEnhancer = {
|
|
89
|
+
name: 'uniqueness',
|
|
90
|
+
errorName: 'duplicate_error',
|
|
91
|
+
matches: (error, _context) => {
|
|
92
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
93
|
+
return (msg.includes('duplicate') ||
|
|
94
|
+
msg.toLowerCase().includes('uniqueness constraint'));
|
|
95
|
+
},
|
|
96
|
+
enhance: async (_error, context) => {
|
|
97
|
+
const { resourceType, recordData } = context;
|
|
98
|
+
if (!recordData)
|
|
99
|
+
return null;
|
|
100
|
+
// Try to find and identify the conflicting record
|
|
101
|
+
const enhancedMessage = await enhanceUniquenessErrorWithSearch(resourceType, recordData);
|
|
102
|
+
if (enhancedMessage) {
|
|
103
|
+
return enhancedMessage;
|
|
104
|
+
}
|
|
105
|
+
// Fallback message if we couldn't find the specific record
|
|
106
|
+
return 'A record with similar data already exists. Check unique fields like domains or email_addresses.';
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=uniqueness-enhancer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uniqueness-enhancer.js","sourceRoot":"","sources":["../../../../../../src/handlers/tool-configs/universal/core/error-enhancers/uniqueness-enhancer.ts"],"names":[],"mappings":"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"}
|