attio-mcp 1.1.10 → 1.2.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 +99 -1
- package/dist/api/attribute-types.d.ts.map +1 -1
- package/dist/api/attribute-types.js +7 -2
- package/dist/api/attribute-types.js.map +1 -1
- package/dist/api/operations/lists.d.ts.map +1 -1
- package/dist/api/operations/lists.js +4 -3
- package/dist/api/operations/lists.js.map +1 -1
- package/dist/api/operations/search.d.ts.map +1 -1
- package/dist/api/operations/search.js +1 -1
- package/dist/api/operations/search.js.map +1 -1
- package/dist/handlers/tool-configs/universal/core/index.d.ts +22 -2
- package/dist/handlers/tool-configs/universal/core/index.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/search-operations.d.ts +22 -2
- package/dist/handlers/tool-configs/universal/core/search-operations.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/core/search-operations.js +1 -1
- package/dist/handlers/tool-configs/universal/core/search-operations.js.map +1 -1
- package/dist/handlers/tool-configs/universal/index.d.ts +22 -2
- package/dist/handlers/tool-configs/universal/index.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/operations/index.js +2 -2
- package/dist/handlers/tool-configs/universal/operations/index.js.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/advanced-schemas.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/advanced-schemas.js +1 -0
- package/dist/handlers/tool-configs/universal/schemas/advanced-schemas.js.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/common/properties.js +1 -1
- package/dist/handlers/tool-configs/universal/schemas/common/properties.js.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/core-schemas.d.ts +22 -2
- package/dist/handlers/tool-configs/universal/schemas/core-schemas.d.ts.map +1 -1
- package/dist/handlers/tool-configs/universal/schemas/core-schemas.js +65 -1
- package/dist/handlers/tool-configs/universal/schemas/core-schemas.js.map +1 -1
- package/dist/handlers/tools/dispatcher/core.d.ts.map +1 -1
- package/dist/handlers/tools/dispatcher/core.js +13 -0
- package/dist/handlers/tools/dispatcher/core.js.map +1 -1
- package/dist/handlers/tools/registry.d.ts +22 -2
- package/dist/handlers/tools/registry.d.ts.map +1 -1
- package/dist/prompts/v1/create-task.v1.d.ts +1 -1
- package/dist/prompts/v1/pipeline-health.v1.d.ts +2 -2
- package/dist/services/workspace-member-resolver.d.ts +55 -0
- package/dist/services/workspace-member-resolver.d.ts.map +1 -0
- package/dist/services/workspace-member-resolver.js +146 -0
- package/dist/services/workspace-member-resolver.js.map +1 -0
- package/dist/utils/client-resolver.d.ts +4 -1
- package/dist/utils/client-resolver.d.ts.map +1 -1
- package/dist/utils/client-resolver.js +57 -33
- package/dist/utils/client-resolver.js.map +1 -1
- package/dist/utils/filters/reference-attribute-helper.d.ts +69 -0
- package/dist/utils/filters/reference-attribute-helper.d.ts.map +1 -0
- package/dist/utils/filters/reference-attribute-helper.js +262 -0
- package/dist/utils/filters/reference-attribute-helper.js.map +1 -0
- package/dist/utils/filters/translators.d.ts +3 -67
- package/dist/utils/filters/translators.d.ts.map +1 -1
- package/dist/utils/filters/translators.js +208 -26
- package/dist/utils/filters/translators.js.map +1 -1
- package/dist/utils/filters/value-validators.d.ts +37 -0
- package/dist/utils/filters/value-validators.d.ts.map +1 -0
- package/dist/utils/filters/value-validators.js +107 -0
- package/dist/utils/filters/value-validators.js.map +1 -0
- package/dist/utils/ttl-cache.d.ts +69 -0
- package/dist/utils/ttl-cache.d.ts.map +1 -0
- package/dist/utils/ttl-cache.js +113 -0
- package/dist/utils/ttl-cache.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/client-resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"client-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/client-resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAqEtC;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,aAAa,CAyFlD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,aAAa,CAOtE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAIvD"}
|
|
@@ -17,20 +17,42 @@ function assertAxiosInstance(value, source) {
|
|
|
17
17
|
'defaults' in candidate &&
|
|
18
18
|
typeof candidate.defaults === 'object';
|
|
19
19
|
if (!hasGetMethod || !hasDefaults) {
|
|
20
|
-
|
|
20
|
+
// Enhanced diagnostic information
|
|
21
|
+
const diagnostics = {
|
|
22
|
+
valueType: typeof value,
|
|
23
|
+
isNull: value === null,
|
|
24
|
+
isUndefined: value === undefined,
|
|
25
|
+
isObject: typeof value === 'object' && value !== null,
|
|
26
|
+
hasGetMethod,
|
|
27
|
+
hasDefaults,
|
|
28
|
+
hasDefaultsProperty: candidate && typeof candidate === 'object' && 'defaults' in candidate,
|
|
29
|
+
defaultsType: candidate && typeof candidate === 'object' && 'defaults' in candidate
|
|
30
|
+
? typeof candidate.defaults
|
|
31
|
+
: 'N/A',
|
|
32
|
+
availableProperties: candidate && typeof candidate === 'object'
|
|
33
|
+
? Object.keys(candidate).slice(0, 10)
|
|
34
|
+
: [],
|
|
35
|
+
};
|
|
36
|
+
if (process.env.MCP_LOG_LEVEL === 'DEBUG') {
|
|
37
|
+
console.error(`[client-resolver:assertAxiosInstance] Validation failed for ${source}:`, diagnostics);
|
|
38
|
+
}
|
|
39
|
+
throw new Error(`${source} returned invalid Axios client instance (hasGetMethod=${hasGetMethod}, hasDefaults=${hasDefaults})`);
|
|
21
40
|
}
|
|
22
41
|
}
|
|
23
42
|
/**
|
|
24
43
|
* Resolves an Attio client instance using the unified interface.
|
|
25
|
-
*
|
|
44
|
+
* Uses getAttioClient() which handles caching, environment detection, and strategy pattern.
|
|
45
|
+
*
|
|
46
|
+
* This simplification fixes Issue #904 client initialization validation failures by using
|
|
47
|
+
* the proven getAttioClient() code path instead of attempting multiple factory methods.
|
|
26
48
|
*/
|
|
27
49
|
export function resolveAttioClient() {
|
|
28
50
|
const mod = AttioClientModule;
|
|
29
|
-
|
|
30
|
-
const envApiKey = process.env.ATTIO_API_KEY;
|
|
31
|
-
const resolvedApiKey = envApiKey || contextApiKey;
|
|
32
|
-
// Debug logging for Issue #891: Track API key resolution
|
|
51
|
+
// Debug logging for API key resolution (informational only)
|
|
33
52
|
if (process.env.MCP_LOG_LEVEL === 'DEBUG') {
|
|
53
|
+
const contextApiKey = getContextApiKey();
|
|
54
|
+
const envApiKey = process.env.ATTIO_API_KEY;
|
|
55
|
+
const resolvedApiKey = envApiKey || contextApiKey;
|
|
34
56
|
console.error('[client-resolver:resolve] API key resolution:', {
|
|
35
57
|
hasEnvApiKey: Boolean(envApiKey),
|
|
36
58
|
envKeyLength: envApiKey?.length || 0,
|
|
@@ -46,47 +68,49 @@ export function resolveAttioClient() {
|
|
|
46
68
|
timestamp: new Date().toISOString(),
|
|
47
69
|
});
|
|
48
70
|
}
|
|
49
|
-
//
|
|
71
|
+
// Use getAttioClient() - it handles all the complexity:
|
|
72
|
+
// - Caching (ClientCache and legacy apiInstance)
|
|
73
|
+
// - Environment detection (E2E, test, production modes)
|
|
74
|
+
// - Strategy pattern (ProductionClientStrategy, E2EClientStrategy, etc.)
|
|
75
|
+
// - API key resolution (env, context, config)
|
|
76
|
+
// This is the proven code path used throughout the codebase
|
|
77
|
+
if (typeof mod.getAttioClient === 'function') {
|
|
78
|
+
if (process.env.MCP_LOG_LEVEL === 'DEBUG') {
|
|
79
|
+
console.error('[client-resolver:resolve] Using getAttioClient()');
|
|
80
|
+
}
|
|
81
|
+
const client = mod.getAttioClient();
|
|
82
|
+
assertAxiosInstance(client, 'getAttioClient()');
|
|
83
|
+
return client;
|
|
84
|
+
}
|
|
85
|
+
// Fallback to createAttioClient with config object
|
|
50
86
|
if (typeof mod.createAttioClient === 'function') {
|
|
87
|
+
if (process.env.MCP_LOG_LEVEL === 'DEBUG') {
|
|
88
|
+
console.error('[client-resolver:resolve] Fallback to createAttioClient(config)');
|
|
89
|
+
}
|
|
51
90
|
try {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
const client = mod.createAttioClient(resolvedApiKey);
|
|
58
|
-
assertAxiosInstance(client, 'createAttioClient(apiKey)');
|
|
59
|
-
return client;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
if (process.env.MCP_LOG_LEVEL === 'DEBUG') {
|
|
63
|
-
console.error('[client-resolver:resolve] Creating client without API key (will fail on first request)');
|
|
64
|
-
}
|
|
65
|
-
// Use config object (new unified interface)
|
|
66
|
-
const config = {};
|
|
67
|
-
const client = mod.createAttioClient(config);
|
|
68
|
-
assertAxiosInstance(client, 'createAttioClient(config)');
|
|
69
|
-
return client;
|
|
70
|
-
}
|
|
91
|
+
const config = {};
|
|
92
|
+
const client = mod.createAttioClient(config);
|
|
93
|
+
assertAxiosInstance(client, 'createAttioClient(config)');
|
|
94
|
+
return client;
|
|
71
95
|
}
|
|
72
96
|
catch (error) {
|
|
73
97
|
if (process.env.MCP_LOG_LEVEL === 'DEBUG') {
|
|
74
98
|
console.error('[client-resolver:resolve] createAttioClient failed:', error);
|
|
75
99
|
}
|
|
76
|
-
// Continue to
|
|
100
|
+
// Continue to last resort
|
|
77
101
|
}
|
|
78
102
|
}
|
|
79
|
-
// Fallback to getAttioClient if createAttioClient fails
|
|
80
|
-
if (typeof mod.getAttioClient === 'function') {
|
|
81
|
-
const client = mod.getAttioClient();
|
|
82
|
-
assertAxiosInstance(client, 'getAttioClient()');
|
|
83
|
-
return client;
|
|
84
|
-
}
|
|
85
103
|
// Last resort: buildAttioClient
|
|
86
104
|
if (typeof mod.buildAttioClient === 'function') {
|
|
105
|
+
const contextApiKey = getContextApiKey();
|
|
106
|
+
const envApiKey = process.env.ATTIO_API_KEY;
|
|
107
|
+
const resolvedApiKey = envApiKey || contextApiKey;
|
|
87
108
|
if (!resolvedApiKey) {
|
|
88
109
|
throw new Error('Attio API key is required for client initialization. Please set ATTIO_API_KEY environment variable.');
|
|
89
110
|
}
|
|
111
|
+
if (process.env.MCP_LOG_LEVEL === 'DEBUG') {
|
|
112
|
+
console.error('[client-resolver:resolve] Last resort: buildAttioClient');
|
|
113
|
+
}
|
|
90
114
|
const client = mod.buildAttioClient({ apiKey: resolvedApiKey });
|
|
91
115
|
assertAxiosInstance(client, 'buildAttioClient()');
|
|
92
116
|
return client;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-resolver.js","sourceRoot":"","sources":["../../src/utils/client-resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAa5D;;;GAGG;AACH,SAAS,mBAAmB,CAC1B,KAAc,EACd,MAAc;IAEd,MAAM,SAAS,GAAG,KAAmD,CAAC;IAEtE,MAAM,YAAY,GAChB,CAAC,CAAC,SAAS;QACX,OAAO,SAAS,KAAK,QAAQ;QAC7B,OAAO,SAAS,CAAC,GAAG,KAAK,UAAU,CAAC;IAEtC,MAAM,WAAW,GACf,YAAY;QACZ,UAAU,IAAI,SAAS;QACvB,OAAO,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC;IAEzC,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"client-resolver.js","sourceRoot":"","sources":["../../src/utils/client-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference Attribute Helper
|
|
3
|
+
*
|
|
4
|
+
* Utilities for detecting and handling reference attributes in filter transformations.
|
|
5
|
+
* Reference attributes (owner, assignee, company, person) require nested field specification
|
|
6
|
+
* in Attio API filter syntax.
|
|
7
|
+
*/
|
|
8
|
+
import { getAttributeTypeInfo } from '../../api/attribute-types.js';
|
|
9
|
+
export { getAttributeTypeInfo };
|
|
10
|
+
/**
|
|
11
|
+
* UUID v4 pattern for detecting UUID values
|
|
12
|
+
* Exported for use in filter translators (PR #904 Phase 2)
|
|
13
|
+
*/
|
|
14
|
+
export declare const UUID_PATTERN: RegExp;
|
|
15
|
+
/**
|
|
16
|
+
* Email pattern for workspace member validation
|
|
17
|
+
*
|
|
18
|
+
* Uses permissive pattern to handle edge cases:
|
|
19
|
+
* - Test environments may use simplified emails (e.g., test@local.dev)
|
|
20
|
+
* - Some valid domains have short TLDs or special characters
|
|
21
|
+
* - Attio API performs canonical validation, so false positives fail fast
|
|
22
|
+
*
|
|
23
|
+
* Pattern validates: non-whitespace + @ + non-whitespace + . + non-whitespace
|
|
24
|
+
* Accepts: user@example.com, test@local.dev, admin@co.uk
|
|
25
|
+
* Rejects: missing @, missing domain, whitespace, no TLD
|
|
26
|
+
* Exported for use in filter translators (PR #904 Phase 2)
|
|
27
|
+
*/
|
|
28
|
+
export declare const EMAIL_PATTERN: RegExp;
|
|
29
|
+
/**
|
|
30
|
+
* Known actor-reference slugs that require special handling in list entry context
|
|
31
|
+
* When resourceType is unavailable, these slugs with UUID values must use referenced_actor_id
|
|
32
|
+
* (not record_id) to generate correct actor-reference filter structure
|
|
33
|
+
* Exported for use in filter translators (PR #904 Phase 2)
|
|
34
|
+
*/
|
|
35
|
+
export declare const KNOWN_ACTOR_REFERENCE_SLUGS: Set<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Per-request cache for attribute type info to avoid repeated lookups
|
|
38
|
+
* Key format: `${resourceType}:${attributeSlug}`
|
|
39
|
+
*/
|
|
40
|
+
export type AttributeTypeCache = Map<string, Awaited<ReturnType<typeof getAttributeTypeInfo>>>;
|
|
41
|
+
/**
|
|
42
|
+
* Check if an attribute is a reference type that requires nested field specification
|
|
43
|
+
*
|
|
44
|
+
* @param resourceType - The resource type (e.g., 'deals', 'companies'), or undefined for slug-based fallback
|
|
45
|
+
* @param attributeSlug - The attribute slug (e.g., 'owner', 'assignee')
|
|
46
|
+
* @param cache - Optional per-request cache to avoid repeated getAttributeTypeInfo calls
|
|
47
|
+
* @returns True if the attribute is a reference type
|
|
48
|
+
*/
|
|
49
|
+
export declare function isReferenceAttribute(resourceType: string | undefined, attributeSlug: string, cache?: AttributeTypeCache): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Determine which field to use for a reference attribute based on the value and type
|
|
52
|
+
*
|
|
53
|
+
* @param value - The filter value (can be UUID, name, or array of UUIDs/names for in/not_in operators)
|
|
54
|
+
* @param attioType - The Attio attribute type (optional)
|
|
55
|
+
* @returns The field name to use ('record_id', 'name', or 'referenced_actor_id' for actor-reference)
|
|
56
|
+
*/
|
|
57
|
+
export declare function determineReferenceField(value: unknown, attioType?: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Get the appropriate reference field for an attribute, considering type-specific mappings
|
|
60
|
+
*
|
|
61
|
+
* @param resourceType - The resource type, or undefined for slug-based fallback
|
|
62
|
+
* @param attributeSlug - The attribute slug
|
|
63
|
+
* @param value - The filter value
|
|
64
|
+
* @param cache - Optional per-request cache to avoid repeated getAttributeTypeInfo calls
|
|
65
|
+
* @returns The field name to use for filtering
|
|
66
|
+
* @throws FilterValidationError if email validation fails for workspace-member fields
|
|
67
|
+
*/
|
|
68
|
+
export declare function getReferenceFieldForAttribute(resourceType: string | undefined, attributeSlug: string, value: unknown, cache?: AttributeTypeCache): Promise<string>;
|
|
69
|
+
//# sourceMappingURL=reference-attribute-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-attribute-helper.d.ts","sourceRoot":"","sources":["../../../src/utils/filters/reference-attribute-helper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAQhE,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAuBhC;;;GAGG;AACH,eAAO,MAAM,YAAY,QACiD,CAAC;AAE3E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,QAA+B,CAAC;AAwB1D;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,aAKtC,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAClC,MAAM,EACN,OAAO,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CACjD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,kBAAkB,GACzB,OAAO,CAAC,OAAO,CAAC,CA+BlB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAuCR;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,EACd,KAAK,CAAC,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CA2HjB"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference Attribute Helper
|
|
3
|
+
*
|
|
4
|
+
* Utilities for detecting and handling reference attributes in filter transformations.
|
|
5
|
+
* Reference attributes (owner, assignee, company, person) require nested field specification
|
|
6
|
+
* in Attio API filter syntax.
|
|
7
|
+
*/
|
|
8
|
+
import { getAttributeTypeInfo } from '../../api/attribute-types.js';
|
|
9
|
+
import { FilterValidationError, FilterErrorCategory, } from '../../errors/api-errors.js';
|
|
10
|
+
import { warn } from '../../utils/logger.js';
|
|
11
|
+
// Re-export getAttributeTypeInfo for use in translators
|
|
12
|
+
export { getAttributeTypeInfo };
|
|
13
|
+
/**
|
|
14
|
+
* Attio attribute types that require reference field nesting
|
|
15
|
+
*/
|
|
16
|
+
const REFERENCE_TYPES = [
|
|
17
|
+
'record-reference',
|
|
18
|
+
'actor-reference',
|
|
19
|
+
'workspace-member',
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Field to use for specific attribute types that require fixed field names
|
|
23
|
+
* Only include types that ALWAYS use the same field regardless of value
|
|
24
|
+
*
|
|
25
|
+
* NOTE: actor-reference fields (like deals.owner) can accept either email OR UUID
|
|
26
|
+
* depending on the value format, so we use heuristic detection instead of forcing email.
|
|
27
|
+
* Only workspace-member typed fields must use email.
|
|
28
|
+
*/
|
|
29
|
+
const REFERENCE_FIELD_MAPPING = {
|
|
30
|
+
'workspace-member': 'email', // workspace members always filter by email
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* UUID v4 pattern for detecting UUID values
|
|
34
|
+
* Exported for use in filter translators (PR #904 Phase 2)
|
|
35
|
+
*/
|
|
36
|
+
export const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
37
|
+
/**
|
|
38
|
+
* Email pattern for workspace member validation
|
|
39
|
+
*
|
|
40
|
+
* Uses permissive pattern to handle edge cases:
|
|
41
|
+
* - Test environments may use simplified emails (e.g., test@local.dev)
|
|
42
|
+
* - Some valid domains have short TLDs or special characters
|
|
43
|
+
* - Attio API performs canonical validation, so false positives fail fast
|
|
44
|
+
*
|
|
45
|
+
* Pattern validates: non-whitespace + @ + non-whitespace + . + non-whitespace
|
|
46
|
+
* Accepts: user@example.com, test@local.dev, admin@co.uk
|
|
47
|
+
* Rejects: missing @, missing domain, whitespace, no TLD
|
|
48
|
+
* Exported for use in filter translators (PR #904 Phase 2)
|
|
49
|
+
*/
|
|
50
|
+
export const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
51
|
+
/**
|
|
52
|
+
* Known reference attribute slugs that commonly require nested field specification
|
|
53
|
+
* Used as fallback when resourceType is unavailable (e.g., list entries)
|
|
54
|
+
*/
|
|
55
|
+
const KNOWN_REFERENCE_SLUGS = new Set([
|
|
56
|
+
'owner',
|
|
57
|
+
'assignee',
|
|
58
|
+
'assignee_id', // workspace-member type that requires email field
|
|
59
|
+
'company',
|
|
60
|
+
'person',
|
|
61
|
+
'primary_contact',
|
|
62
|
+
'workspace_member',
|
|
63
|
+
'created_by',
|
|
64
|
+
'modified_by',
|
|
65
|
+
]);
|
|
66
|
+
/**
|
|
67
|
+
* Slugs that ALWAYS require email field (workspace-member type)
|
|
68
|
+
* Note: actor-reference slugs like 'owner', 'assignee' use flexible detection (UUID vs email vs name)
|
|
69
|
+
*/
|
|
70
|
+
const WORKSPACE_MEMBER_SLUGS = new Set(['workspace_member', 'assignee_id']);
|
|
71
|
+
/**
|
|
72
|
+
* Known actor-reference slugs that require special handling in list entry context
|
|
73
|
+
* When resourceType is unavailable, these slugs with UUID values must use referenced_actor_id
|
|
74
|
+
* (not record_id) to generate correct actor-reference filter structure
|
|
75
|
+
* Exported for use in filter translators (PR #904 Phase 2)
|
|
76
|
+
*/
|
|
77
|
+
export const KNOWN_ACTOR_REFERENCE_SLUGS = new Set([
|
|
78
|
+
'owner',
|
|
79
|
+
'assignee',
|
|
80
|
+
'created_by',
|
|
81
|
+
'modified_by',
|
|
82
|
+
]);
|
|
83
|
+
/**
|
|
84
|
+
* Check if an attribute is a reference type that requires nested field specification
|
|
85
|
+
*
|
|
86
|
+
* @param resourceType - The resource type (e.g., 'deals', 'companies'), or undefined for slug-based fallback
|
|
87
|
+
* @param attributeSlug - The attribute slug (e.g., 'owner', 'assignee')
|
|
88
|
+
* @param cache - Optional per-request cache to avoid repeated getAttributeTypeInfo calls
|
|
89
|
+
* @returns True if the attribute is a reference type
|
|
90
|
+
*/
|
|
91
|
+
export async function isReferenceAttribute(resourceType, attributeSlug, cache) {
|
|
92
|
+
// If resourceType is unavailable (e.g., list entries), use slug-based fallback
|
|
93
|
+
if (!resourceType) {
|
|
94
|
+
return KNOWN_REFERENCE_SLUGS.has(attributeSlug);
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
// Check cache first
|
|
98
|
+
const cacheKey = `${resourceType}:${attributeSlug}`;
|
|
99
|
+
let typeInfo = cache?.get(cacheKey);
|
|
100
|
+
if (!typeInfo) {
|
|
101
|
+
typeInfo = await getAttributeTypeInfo(resourceType, attributeSlug);
|
|
102
|
+
cache?.set(cacheKey, typeInfo);
|
|
103
|
+
}
|
|
104
|
+
return REFERENCE_TYPES.includes(typeInfo.attioType);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
// If metadata lookup fails, fall back to slug-based detection
|
|
108
|
+
warn('filters/reference-attribute-helper', `Metadata lookup failed for ${resourceType}.${attributeSlug}, using slug-based fallback`, {
|
|
109
|
+
resourceType,
|
|
110
|
+
attributeSlug,
|
|
111
|
+
reason: 'metadata_lookup_failed',
|
|
112
|
+
error: error instanceof Error ? error.message : String(error),
|
|
113
|
+
});
|
|
114
|
+
return KNOWN_REFERENCE_SLUGS.has(attributeSlug);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Determine which field to use for a reference attribute based on the value and type
|
|
119
|
+
*
|
|
120
|
+
* @param value - The filter value (can be UUID, name, or array of UUIDs/names for in/not_in operators)
|
|
121
|
+
* @param attioType - The Attio attribute type (optional)
|
|
122
|
+
* @returns The field name to use ('record_id', 'name', or 'referenced_actor_id' for actor-reference)
|
|
123
|
+
*/
|
|
124
|
+
export function determineReferenceField(value, attioType) {
|
|
125
|
+
// Actor-reference attributes use referenced_actor_id (always UUID)
|
|
126
|
+
if (attioType === 'actor-reference') {
|
|
127
|
+
return 'referenced_actor_id';
|
|
128
|
+
}
|
|
129
|
+
// Handle array values (for in/not_in operators)
|
|
130
|
+
if (Array.isArray(value)) {
|
|
131
|
+
// Empty arrays default to name field
|
|
132
|
+
if (value.length === 0) {
|
|
133
|
+
return 'name';
|
|
134
|
+
}
|
|
135
|
+
// Check if all elements are UUID strings
|
|
136
|
+
const allUUIDs = value.every((v) => typeof v === 'string' && UUID_PATTERN.test(v));
|
|
137
|
+
const allNonUUIDs = value.every((v) => typeof v === 'string' && !UUID_PATTERN.test(v));
|
|
138
|
+
// Reject mixed-type arrays (some UUIDs, some names)
|
|
139
|
+
if (!allUUIDs && !allNonUUIDs) {
|
|
140
|
+
throw new FilterValidationError(`Mixed UUID and non-UUID values not supported in array filters. ` +
|
|
141
|
+
`Received array with both types. Use separate filters or ensure all values are the same type.`, FilterErrorCategory.VALUE);
|
|
142
|
+
}
|
|
143
|
+
return allUUIDs ? 'record_id' : 'name';
|
|
144
|
+
}
|
|
145
|
+
// Handle single values
|
|
146
|
+
if (typeof value === 'string' && UUID_PATTERN.test(value)) {
|
|
147
|
+
return 'record_id';
|
|
148
|
+
}
|
|
149
|
+
// Otherwise use name field
|
|
150
|
+
return 'name';
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get the appropriate reference field for an attribute, considering type-specific mappings
|
|
154
|
+
*
|
|
155
|
+
* @param resourceType - The resource type, or undefined for slug-based fallback
|
|
156
|
+
* @param attributeSlug - The attribute slug
|
|
157
|
+
* @param value - The filter value
|
|
158
|
+
* @param cache - Optional per-request cache to avoid repeated getAttributeTypeInfo calls
|
|
159
|
+
* @returns The field name to use for filtering
|
|
160
|
+
* @throws FilterValidationError if email validation fails for workspace-member fields
|
|
161
|
+
*/
|
|
162
|
+
export async function getReferenceFieldForAttribute(resourceType, attributeSlug, value, cache) {
|
|
163
|
+
// Special case: workspace_member and assignee_id slugs ALWAYS use email
|
|
164
|
+
// regardless of metadata availability
|
|
165
|
+
if (attributeSlug === 'workspace_member' || attributeSlug === 'assignee_id') {
|
|
166
|
+
// Validate email format
|
|
167
|
+
if (typeof value !== 'string' || !EMAIL_PATTERN.test(value)) {
|
|
168
|
+
throw new FilterValidationError(`Invalid email format for ${attributeSlug}: "${value}". Expected valid email address.`, FilterErrorCategory.VALUE);
|
|
169
|
+
}
|
|
170
|
+
return 'email';
|
|
171
|
+
}
|
|
172
|
+
// If resourceType is available, use metadata to determine field
|
|
173
|
+
if (resourceType) {
|
|
174
|
+
try {
|
|
175
|
+
// Check cache first
|
|
176
|
+
const cacheKey = `${resourceType}:${attributeSlug}`;
|
|
177
|
+
let typeInfo = cache?.get(cacheKey);
|
|
178
|
+
if (!typeInfo) {
|
|
179
|
+
typeInfo = await getAttributeTypeInfo(resourceType, attributeSlug);
|
|
180
|
+
cache?.set(cacheKey, typeInfo);
|
|
181
|
+
}
|
|
182
|
+
// Check for attribute-specific mapping (only workspace-member type requires fixed email)
|
|
183
|
+
if (REFERENCE_FIELD_MAPPING[typeInfo.attioType]) {
|
|
184
|
+
const field = REFERENCE_FIELD_MAPPING[typeInfo.attioType];
|
|
185
|
+
// Validate email if this is an email field
|
|
186
|
+
if (field === 'email') {
|
|
187
|
+
if (typeof value !== 'string' || !EMAIL_PATTERN.test(value)) {
|
|
188
|
+
throw new FilterValidationError(`Invalid email format for ${attributeSlug}: "${value}". Expected valid email address.`, FilterErrorCategory.VALUE);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return field;
|
|
192
|
+
}
|
|
193
|
+
// Actor-reference fields (e.g., owner, assignee) support flexible filtering:
|
|
194
|
+
// - Email address → filter by email field
|
|
195
|
+
// - UUID (workspace member ID) → filter by referenced_actor_id (requires referenced_actor_type)
|
|
196
|
+
// - Name (plain text) → filter by name field
|
|
197
|
+
if (typeInfo.attioType === 'actor-reference') {
|
|
198
|
+
if (typeof value !== 'string') {
|
|
199
|
+
throw new FilterValidationError(`Actor-reference attribute "${attributeSlug}" requires a string value (email, name, or UUID). Got: ${typeof value}`, FilterErrorCategory.VALUE);
|
|
200
|
+
}
|
|
201
|
+
// Detect value type and return appropriate field
|
|
202
|
+
if (EMAIL_PATTERN.test(value)) {
|
|
203
|
+
return 'email';
|
|
204
|
+
}
|
|
205
|
+
else if (UUID_PATTERN.test(value)) {
|
|
206
|
+
return 'referenced_actor_id';
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// Plain text name
|
|
210
|
+
return 'name';
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Fall back to UUID vs name detection for record-reference types
|
|
214
|
+
return determineReferenceField(value, typeInfo.attioType);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
// Re-throw FilterValidationError
|
|
218
|
+
if (error instanceof FilterValidationError) {
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
// Fall through to slug-based detection if metadata lookup fails
|
|
222
|
+
warn('filters/reference-attribute-helper', `Metadata lookup failed in getReferenceFieldForAttribute for ${resourceType}.${attributeSlug}, using slug-based fallback`, {
|
|
223
|
+
resourceType,
|
|
224
|
+
attributeSlug,
|
|
225
|
+
reason: 'metadata_lookup_failed',
|
|
226
|
+
error: error instanceof Error ? error.message : String(error),
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// ResourceType unavailable or metadata lookup failed - use slug-based detection
|
|
231
|
+
// Check if this is a known workspace member slug (requires email field)
|
|
232
|
+
if (WORKSPACE_MEMBER_SLUGS.has(attributeSlug)) {
|
|
233
|
+
// Validate email format
|
|
234
|
+
if (typeof value !== 'string' || !EMAIL_PATTERN.test(value)) {
|
|
235
|
+
throw new FilterValidationError(`Invalid email format for ${attributeSlug}: "${value}". Expected valid email address. Workspace member attributes (owner, assignee, etc.) require email addresses.`, FilterErrorCategory.VALUE);
|
|
236
|
+
}
|
|
237
|
+
return 'email';
|
|
238
|
+
}
|
|
239
|
+
// Special handling for known actor-reference slugs (owner, assignee, created_by, modified_by)
|
|
240
|
+
// When resourceType unavailable (e.g., list entries), we can't query metadata but can use slug patterns
|
|
241
|
+
if (KNOWN_ACTOR_REFERENCE_SLUGS.has(attributeSlug)) {
|
|
242
|
+
// Actor-reference attributes support email, UUID, or name filtering
|
|
243
|
+
if (typeof value !== 'string') {
|
|
244
|
+
throw new FilterValidationError(`Actor-reference attribute "${attributeSlug}" requires a string value (email, name, or UUID). Got: ${typeof value}`, FilterErrorCategory.VALUE);
|
|
245
|
+
}
|
|
246
|
+
// Detect value type and return appropriate field
|
|
247
|
+
if (EMAIL_PATTERN.test(value)) {
|
|
248
|
+
return 'email';
|
|
249
|
+
}
|
|
250
|
+
else if (UUID_PATTERN.test(value)) {
|
|
251
|
+
// UUID values must use referenced_actor_id for actor-reference structure
|
|
252
|
+
return 'referenced_actor_id';
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
// Plain text name
|
|
256
|
+
return 'name';
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// For other reference slugs (company, person, etc.), use basic heuristic detection (UUID vs name)
|
|
260
|
+
return determineReferenceField(value);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=reference-attribute-helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-attribute-helper.js","sourceRoot":"","sources":["../../../src/utils/filters/reference-attribute-helper.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,73 +12,9 @@
|
|
|
12
12
|
* - Reverse transformation (API to MCP)
|
|
13
13
|
*/
|
|
14
14
|
import { ListEntryFilters, ListEntryFilter, AttioApiFilter, AttioQueryApiFilter, FilterConditionType } from './types.js';
|
|
15
|
-
|
|
16
|
-
* Transforms list entry filters to the format expected by the Attio API
|
|
17
|
-
*
|
|
18
|
-
* This is the main transformation function that converts MCP filter specifications
|
|
19
|
-
* into the format expected by the Attio API. It handles both AND and OR logical
|
|
20
|
-
* operators and provides comprehensive validation.
|
|
21
|
-
*
|
|
22
|
-
* **Key Features:**
|
|
23
|
-
* - Validates filter structure using centralized validation utilities
|
|
24
|
-
* - Supports both AND logic (default) and OR logic (matchAny: true)
|
|
25
|
-
* - Handles empty filter arrays gracefully (returns empty object)
|
|
26
|
-
* - Preserves filter condition types and values
|
|
27
|
-
* - Provides detailed error messages with examples on validation failure
|
|
28
|
-
*
|
|
29
|
-
* @param filters - Filter configuration from the MCP API (may have optional filters array)
|
|
30
|
-
* @param validateConditions - Whether to validate condition types against known Attio API operators
|
|
31
|
-
* @returns Transformed filter object for Attio API, or empty object if no valid filters
|
|
32
|
-
* @throws FilterValidationError if validation fails with consistent error messages and examples
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* // Simple filter with a single condition
|
|
36
|
-
* const simpleFilter = {
|
|
37
|
-
* filters: [
|
|
38
|
-
* {
|
|
39
|
-
* attribute: { slug: 'name' },
|
|
40
|
-
* condition: 'contains',
|
|
41
|
-
* value: 'Company Inc'
|
|
42
|
-
* }
|
|
43
|
-
* ]
|
|
44
|
-
* };
|
|
45
|
-
*
|
|
46
|
-
* // Filter with OR logic between conditions
|
|
47
|
-
* const orFilter = {
|
|
48
|
-
* filters: [
|
|
49
|
-
* {
|
|
50
|
-
* attribute: { slug: 'name' },
|
|
51
|
-
* condition: 'contains',
|
|
52
|
-
* value: 'Inc'
|
|
53
|
-
* },
|
|
54
|
-
* {
|
|
55
|
-
* attribute: { slug: 'industry' },
|
|
56
|
-
* condition: 'equals',
|
|
57
|
-
* value: 'Technology'
|
|
58
|
-
* }
|
|
59
|
-
* ],
|
|
60
|
-
* matchAny: true // Use OR logic
|
|
61
|
-
* };
|
|
62
|
-
*
|
|
63
|
-
* // Filter with multiple conditions (AND logic by default)
|
|
64
|
-
* const multipleFilter = {
|
|
65
|
-
* filters: [
|
|
66
|
-
* {
|
|
67
|
-
* attribute: { slug: 'name' },
|
|
68
|
-
* condition: 'contains',
|
|
69
|
-
* value: 'Inc'
|
|
70
|
-
* },
|
|
71
|
-
* {
|
|
72
|
-
* attribute: { slug: 'website' },
|
|
73
|
-
* condition: 'contains',
|
|
74
|
-
* value: '.com'
|
|
75
|
-
* }
|
|
76
|
-
* ]
|
|
77
|
-
* };
|
|
78
|
-
*/
|
|
79
|
-
export declare function transformFiltersToApiFormat(filters: ListEntryFilters | undefined, validateConditions?: boolean, isListEntryContext?: boolean): {
|
|
15
|
+
export declare function transformFiltersToApiFormat(filters: ListEntryFilters | undefined, validateConditions?: boolean, isListEntryContext?: boolean, resourceType?: string): Promise<{
|
|
80
16
|
filter?: AttioApiFilter;
|
|
81
|
-
}
|
|
17
|
+
}>;
|
|
82
18
|
/**
|
|
83
19
|
* Transforms list entry filters to the new Query API format with path and constraints
|
|
84
20
|
*
|
|
@@ -95,7 +31,7 @@ export declare function transformFiltersToQueryApiFormat(filters: ListEntryFilte
|
|
|
95
31
|
* Converts a single filter operator to API format
|
|
96
32
|
*
|
|
97
33
|
* @param operator - The operator to convert (e.g., 'equals', 'contains')
|
|
98
|
-
* @returns The operator in API format (e.g., '$
|
|
34
|
+
* @returns The operator in API format (e.g., '$eq', '$contains')
|
|
99
35
|
*/
|
|
100
36
|
export declare function convertOperatorToApiFormat(operator: string): string;
|
|
101
37
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translators.d.ts","sourceRoot":"","sources":["../../../src/utils/filters/translators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"translators.d.ts","sourceRoot":"","sources":["../../../src/utils/filters/translators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,YAAY,CAAC;AAkIpB,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,kBAAkB,GAAE,OAAc,EAClC,kBAAkB,GAAE,OAAe,EACnC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,CAkGtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,kBAAkB,GAAE,OAAc,GACjC,mBAAmB,CAqGrB;AAgbD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAOpE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAaT;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,eAAe,GACtB,cAAc,CAoBhB;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,cAAc,GACxB,gBAAgB,CA6ClB"}
|