* Resolve a const reference from a types file. * Handles nested const references recursively. * * @param constName - The const name to resolve (e.g., "SCHEDULE_DATA_OUTPUT_PROPERTIES") * @param toolPrefix - The tool prefix/service name (e.g., "calcom") * @param depth - Recursion depth to preven
( constName: string, toolPrefix: string, depth = 0 )
| 1366 | * @returns Resolved properties object or null if not found |
| 1367 | */ |
| 1368 | function resolveConstReference( |
| 1369 | constName: string, |
| 1370 | toolPrefix: string, |
| 1371 | depth = 0 |
| 1372 | ): Record<string, any> | null { |
| 1373 | // Prevent infinite recursion |
| 1374 | if (depth > 10) { |
| 1375 | console.warn(`Max recursion depth reached resolving const: ${constName}`) |
| 1376 | return null |
| 1377 | } |
| 1378 | |
| 1379 | // Check cache first |
| 1380 | const cacheKey = `${toolPrefix}:${constName}` |
| 1381 | if (constResolutionCache.has(cacheKey)) { |
| 1382 | return constResolutionCache.get(cacheKey)! |
| 1383 | } |
| 1384 | |
| 1385 | // Read the types file for this tool |
| 1386 | const typesFilePath = path.join(rootDir, `apps/sim/tools/${toolPrefix}/types.ts`) |
| 1387 | if (!fs.existsSync(typesFilePath)) { |
| 1388 | // Try to find const in the tool file itself |
| 1389 | return null |
| 1390 | } |
| 1391 | |
| 1392 | const typesContent = fs.readFileSync(typesFilePath, 'utf-8') |
| 1393 | |
| 1394 | // Find the const definition |
| 1395 | // Pattern: export const CONST_NAME = { ... } as const |
| 1396 | const constRegex = new RegExp( |
| 1397 | `export\\s+const\\s+${constName}\\s*(?::\\s*[^=]+)?\\s*=\\s*\\{`, |
| 1398 | 'g' |
| 1399 | ) |
| 1400 | const constMatch = constRegex.exec(typesContent) |
| 1401 | |
| 1402 | if (!constMatch) { |
| 1403 | return null |
| 1404 | } |
| 1405 | |
| 1406 | // Extract the const content |
| 1407 | const startIndex = constMatch.index + constMatch[0].length - 1 |
| 1408 | const endIndex = findMatchingClose(typesContent, startIndex) |
| 1409 | |
| 1410 | if (endIndex === -1) { |
| 1411 | return null |
| 1412 | } |
| 1413 | |
| 1414 | const constContent = typesContent.substring(startIndex + 1, endIndex - 1).trim() |
| 1415 | |
| 1416 | // Check if this const defines a complete output field (has type property) |
| 1417 | // like EVENT_TYPE_OUTPUT = { type: 'object', description: '...', properties: {...} } |
| 1418 | const typeMatch = constContent.match(/^\s*type\s*:\s*['"]([^'"]+)['"]/) |
| 1419 | if (typeMatch) { |
| 1420 | // This is a complete output definition - use parseConstFieldContent |
| 1421 | const result = parseConstFieldContent(constContent, toolPrefix, typesContent, depth + 1) |
| 1422 | if (result) { |
| 1423 | constResolutionCache.set(cacheKey, result) |
| 1424 | } |
| 1425 | return result |
no test coverage detected