From 088fc1a109267136ebd99d6bae6728d8d47ccb5a Mon Sep 17 00:00:00 2001 From: Rohit Date: Wed, 26 Feb 2025 23:52:28 +0530 Subject: [PATCH] feat: add infer field types --- .../integrations/airtable.ts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/server/src/workflow-management/integrations/airtable.ts b/server/src/workflow-management/integrations/airtable.ts index 5b09c608..93474721 100644 --- a/server/src/workflow-management/integrations/airtable.ts +++ b/server/src/workflow-management/integrations/airtable.ts @@ -242,13 +242,18 @@ async function createAirtableField( tableId: string, retries = MAX_RETRIES ): Promise { - try { + try { + const fieldType = inferFieldType(sampleValue); + + console.log(`Creating field ${fieldName} with type ${fieldType}`); + const response = await axios.post( `https://api.airtable.com/v0/meta/bases/${baseId}/tables/${tableId}/fields`, - { name: fieldName }, + { name: fieldName, type: fieldType }, { headers: { Authorization: `Bearer ${accessToken}` } } ); + logger.log('info', `Created field: ${fieldName} (${fieldType})`); return response.data; } catch (error: any) { if (retries > 0 && error.response?.status === 429) { @@ -267,6 +272,27 @@ async function createAirtableField( } } +function inferFieldType(value: any): string { + if (value === null || value === undefined) return 'singleLineText'; + if (typeof value === 'number') return 'number'; + if (typeof value === 'boolean') return 'checkbox'; + if (value instanceof Date) return 'dateTime'; + if (Array.isArray(value)) { + return value.length > 0 && typeof value[0] === 'object' ? 'multipleRecordLinks' : 'multipleSelects'; + } + if (typeof value === 'string' && isValidUrl(value)) return 'url'; + return 'singleLineText'; +} + +function isValidUrl(str: string): boolean { + try { + new URL(str); + return true; + } catch (_) { + return false; + } +} + export const processAirtableUpdates = async () => { while (true) { let hasPendingTasks = false;