mirror of
				https://github.com/lingble/twenty.git
				synced 2025-10-30 20:27:55 +00:00 
			
		
		
		
	7203 support emails links phones in zapier inputs 2 (#7562)
## Done - add `EMAILS`, `PHONES`, `LINKS`, `RICH_TEXT`, `POSITION`, and `ARRAY` field support in Twenty zapier integration - fix `twenty-zapier` package tests and requirements ## Emails <img width="791" alt="image" src="https://github.com/user-attachments/assets/7987a1a2-6076-4715-9221-d4a1898b7634"> ## Links <img width="797" alt="image" src="https://github.com/user-attachments/assets/b94ce972-fae2-4953-b9e8-79c0478f5f60"> ## Phones <img width="789" alt="image" src="https://github.com/user-attachments/assets/7234eaaf-40b8-4772-8880-c58ba47618c5"> ## Array <img width="834" alt="image" src="https://github.com/user-attachments/assets/99cb6795-e428-40ea-9c3a-d52561c2c6e1">
This commit is contained in:
		
							
								
								
									
										9
									
								
								packages/twenty-zapier/jest.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								packages/twenty-zapier/jest.config.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| module.exports = { | ||||
|   preset: 'ts-jest', | ||||
|   testEnvironment: 'node', | ||||
|   transform: { | ||||
|     '^.+\\.ts?$': 'ts-jest', | ||||
|   }, | ||||
|   moduleFileExtensions: ['ts', 'js'], | ||||
|   transformIgnorePatterns: ['/node_modules/'], | ||||
| }; | ||||
| @@ -25,6 +25,7 @@ | ||||
|     "convertedByCLIVersion": "15.4.1" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "dotenv": "^16.4.5", | ||||
|     "zapier-platform-core": "15.5.1" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { computeInputFields } from '../../utils/computeInputFields'; | ||||
| import { InputField } from '../../utils/data.types'; | ||||
| import { FieldMetadataType, InputField } from '../../utils/data.types'; | ||||
|  | ||||
| describe('computeInputFields', () => { | ||||
|   test('should create Person input fields properly', () => { | ||||
| @@ -11,7 +11,7 @@ describe('computeInputFields', () => { | ||||
|         edges: [ | ||||
|           { | ||||
|             node: { | ||||
|               type: 'RELATION', | ||||
|               type: FieldMetadataType.RELATION, | ||||
|               name: 'favorites', | ||||
|               label: 'Favorites', | ||||
|               description: 'Favorites linked to the contact', | ||||
| @@ -21,7 +21,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'CURRENCY', | ||||
|               type: FieldMetadataType.CURRENCY, | ||||
|               name: 'annualSalary', | ||||
|               label: 'Annual Salary', | ||||
|               description: 'Annual Salary of the Person', | ||||
| @@ -31,7 +31,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'TEXT', | ||||
|               type: FieldMetadataType.TEXT, | ||||
|               name: 'jobTitle', | ||||
|               label: 'Job Title', | ||||
|               description: 'Contact’s job title', | ||||
| @@ -43,7 +43,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'DATE_TIME', | ||||
|               type: FieldMetadataType.DATE_TIME, | ||||
|               name: 'updatedAt', | ||||
|               label: 'Update date', | ||||
|               description: null, | ||||
| @@ -55,7 +55,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'FULL_NAME', | ||||
|               type: FieldMetadataType.FULL_NAME, | ||||
|               name: 'name', | ||||
|               label: 'Name', | ||||
|               description: 'Contact’s name', | ||||
| @@ -68,7 +68,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'UUID', | ||||
|               type: FieldMetadataType.UUID, | ||||
|               name: 'id', | ||||
|               label: 'Id', | ||||
|               description: null, | ||||
| @@ -81,7 +81,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'NUMBER', | ||||
|               type: FieldMetadataType.NUMBER, | ||||
|               name: 'recordPosition', | ||||
|               label: 'RecordPosition', | ||||
|               description: 'Record Position', | ||||
| @@ -91,7 +91,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'LINK', | ||||
|               type: FieldMetadataType.LINK, | ||||
|               name: 'xLink', | ||||
|               label: 'X', | ||||
|               description: 'Contact’s X/Twitter account', | ||||
| @@ -101,7 +101,17 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'EMAIL', | ||||
|               type: FieldMetadataType.LINKS, | ||||
|               name: 'whatsapp', | ||||
|               label: 'Whatsapp', | ||||
|               description: 'Contact’s Whatsapp account', | ||||
|               isNullable: true, | ||||
|               defaultValue: null, | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: FieldMetadataType.EMAIL, | ||||
|               name: 'email', | ||||
|               label: 'Email', | ||||
|               description: 'Contact’s Email', | ||||
| @@ -113,7 +123,7 @@ describe('computeInputFields', () => { | ||||
|           }, | ||||
|           { | ||||
|             node: { | ||||
|               type: 'UUID', | ||||
|               type: FieldMetadataType.UUID, | ||||
|               name: 'companyId', | ||||
|               label: 'Company id (foreign key)', | ||||
|               description: 'Contact’s company id foreign key', | ||||
| @@ -190,6 +200,27 @@ describe('computeInputFields', () => { | ||||
|         helpText: 'Contact’s X/Twitter account: Link Label', | ||||
|         required: false, | ||||
|       }, | ||||
|       { | ||||
|         key: 'whatsapp__url', | ||||
|         label: 'Whatsapp: Url', | ||||
|         type: 'string', | ||||
|         helpText: 'Contact’s Whatsapp account: Link Url', | ||||
|         required: false, | ||||
|       }, | ||||
|       { | ||||
|         key: 'whatsapp__label', | ||||
|         label: 'Whatsapp: Label', | ||||
|         type: 'string', | ||||
|         helpText: 'Contact’s Whatsapp account: Link Label', | ||||
|         required: false, | ||||
|       }, | ||||
|       { | ||||
|         key: 'whatsapp__secondaryLinks', | ||||
|         label: 'Whatsapp: Secondary Lings', | ||||
|         type: 'string', | ||||
|         helpText: 'Contact’s Whatsapp account: Link Label', | ||||
|         required: false, | ||||
|       }, | ||||
|       { | ||||
|         key: 'email', | ||||
|         label: 'Email', | ||||
|   | ||||
| @@ -14,6 +14,20 @@ describe('utils.handleQueryParams', () => { | ||||
|       domainName: 'Company Domain Name', | ||||
|       linkedinUrl__url: '/linkedin_url', | ||||
|       linkedinUrl__label: 'Test linkedinUrl', | ||||
|       whatsapp__primaryLinkUrl: '/whatsapp_url', | ||||
|       whatsapp__primaryLinkLabel: 'Whatsapp Link', | ||||
|       whatsapp__secondaryLinks: [ | ||||
|         "{url: '/secondary_whatsapp_url',label: 'Secondary Whatsapp Link'}", | ||||
|       ], | ||||
|       emails: { | ||||
|         primaryEmail: 'primary@email.com', | ||||
|         additionalEmails: ['secondary@email.com'], | ||||
|       }, | ||||
|       phones: { | ||||
|         primaryPhoneNumber: '322110011', | ||||
|         primaryPhoneCountryCode: '+33', | ||||
|         additionalPhones: ["{ phoneNumber: '322110012', countryCode: '+33' }"], | ||||
|       }, | ||||
|       xUrl__url: '/x_url', | ||||
|       xUrl__label: 'Test xUrl', | ||||
|       annualRecurringRevenue: 100000, | ||||
| @@ -23,9 +37,12 @@ describe('utils.handleQueryParams', () => { | ||||
|     const result = handleQueryParams(inputData); | ||||
|     const expectedResult = | ||||
|       'name: "Company Name", ' + | ||||
|       'address: { addressCity: "Paris" }, ' + | ||||
|       'address: {addressCity: "Paris"}, ' + | ||||
|       'domainName: "Company Domain Name", ' + | ||||
|       'linkedinUrl: {url: "/linkedin_url", label: "Test linkedinUrl"}, ' + | ||||
|       'whatsapp: {primaryLinkUrl: "/whatsapp_url", primaryLinkLabel: "Whatsapp Link", secondaryLinks: [{url: \'/secondary_whatsapp_url\',label: \'Secondary Whatsapp Link\'}]}, ' + | ||||
|       'emails: {primaryEmail: "primary@email.com", additionalEmails: ["secondary@email.com"]}, ' + | ||||
|       'phones: {primaryPhoneNumber: "322110011", primaryPhoneCountryCode: "+33", additionalPhones: [{ phoneNumber: \'322110012\', countryCode: \'+33\' }]}, ' + | ||||
|       'xUrl: {url: "/x_url", label: "Test xUrl"}, ' + | ||||
|       'annualRecurringRevenue: 100000, ' + | ||||
|       'idealCustomerProfile: true, ' + | ||||
|   | ||||
| @@ -5,15 +5,21 @@ import { | ||||
|   NodeField, | ||||
| } from '../utils/data.types'; | ||||
|  | ||||
| const getListFromFieldMetadataType = (fieldMetadataType: FieldMetadataType) => { | ||||
|   return fieldMetadataType === FieldMetadataType.ARRAY; | ||||
| }; | ||||
|  | ||||
| const getTypeFromFieldMetadataType = ( | ||||
|   fieldMetadataType: string, | ||||
|   fieldMetadataType: FieldMetadataType, | ||||
| ): string | undefined => { | ||||
|   switch (fieldMetadataType) { | ||||
|     case FieldMetadataType.UUID: | ||||
|     case FieldMetadataType.TEXT: | ||||
|     case FieldMetadataType.RICH_TEXT: | ||||
|     case FieldMetadataType.PHONE: | ||||
|     case FieldMetadataType.EMAIL: | ||||
|     case FieldMetadataType.LINK: | ||||
|     case FieldMetadataType.ARRAY: | ||||
|     case FieldMetadataType.RATING: | ||||
|       return 'string'; | ||||
|     case FieldMetadataType.DATE_TIME: | ||||
| @@ -23,6 +29,7 @@ const getTypeFromFieldMetadataType = ( | ||||
|     case FieldMetadataType.BOOLEAN: | ||||
|       return 'boolean'; | ||||
|     case FieldMetadataType.NUMBER: | ||||
|     case FieldMetadataType.POSITION: | ||||
|       return 'integer'; | ||||
|     case FieldMetadataType.NUMERIC: | ||||
|       return 'number'; | ||||
| @@ -35,7 +42,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|   switch (nodeField.type) { | ||||
|     case FieldMetadataType.FULL_NAME: { | ||||
|       const firstName: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'firstName', | ||||
|         label: 'First Name', | ||||
|         description: 'First Name', | ||||
| @@ -43,7 +50,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const lastName: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'lastName', | ||||
|         label: 'Last Name', | ||||
|         description: 'Last Name', | ||||
| @@ -54,7 +61,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|     } | ||||
|     case FieldMetadataType.LINK: { | ||||
|       const url: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'url', | ||||
|         label: 'Url', | ||||
|         description: 'Link Url', | ||||
| @@ -62,7 +69,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const label: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'label', | ||||
|         label: 'Label', | ||||
|         description: 'Link Label', | ||||
| @@ -73,7 +80,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|     } | ||||
|     case FieldMetadataType.CURRENCY: { | ||||
|       const amountMicros: NodeField = { | ||||
|         type: 'NUMBER', | ||||
|         type: FieldMetadataType.NUMBER, | ||||
|         name: 'amountMicros', | ||||
|         label: 'Amount Micros', | ||||
|         description: 'Amount Micros. eg: set 3210000 for 3.21$', | ||||
| @@ -81,7 +88,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const currencyCode: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'currencyCode', | ||||
|         label: 'Currency Code', | ||||
|         description: 'Currency Code. eg: USD, EUR, etc...', | ||||
| @@ -92,7 +99,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|     } | ||||
|     case FieldMetadataType.ADDRESS: { | ||||
|       const address1: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'addressStreet1', | ||||
|         label: 'Address', | ||||
|         description: 'Address', | ||||
| @@ -100,7 +107,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const address2: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'addressStreet2', | ||||
|         label: 'Address 2', | ||||
|         description: 'Address 2', | ||||
| @@ -108,7 +115,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const city: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'addressCity', | ||||
|         label: 'City', | ||||
|         description: 'City', | ||||
| @@ -116,7 +123,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const state: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'addressState', | ||||
|         label: 'State', | ||||
|         description: 'State', | ||||
| @@ -124,7 +131,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const postalCode: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'addressPostalCode', | ||||
|         label: 'Postal Code', | ||||
|         description: 'Postal Code', | ||||
| @@ -132,7 +139,7 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const country: NodeField = { | ||||
|         type: 'TEXT', | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'addressCountry', | ||||
|         label: 'Country', | ||||
|         description: 'Country', | ||||
| @@ -141,6 +148,84 @@ const get_subfieldsFromField = (nodeField: NodeField): NodeField[] => { | ||||
|       }; | ||||
|       return [address1, address2, city, state, postalCode, country]; | ||||
|     } | ||||
|     case FieldMetadataType.PHONES: { | ||||
|       const primaryPhoneNumber: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'primaryPhoneNumber', | ||||
|         label: 'Primary Phone Number', | ||||
|         description: 'Primary Phone Number. 600112233', | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const primaryPhoneCountryCode: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'primaryPhoneCountryCode', | ||||
|         label: 'Primary Phone Country Code', | ||||
|         description: 'Primary Phone Country Code. eg: +33', | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const additionalPhones: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'additionalPhones', | ||||
|         label: 'Additional Phones', | ||||
|         description: 'Additional Phones', | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|         placeholder: '{ number: "", countryCode: "" }', | ||||
|         list: true, | ||||
|       }; | ||||
|       return [primaryPhoneNumber, primaryPhoneCountryCode, additionalPhones]; | ||||
|     } | ||||
|     case FieldMetadataType.EMAILS: { | ||||
|       const primaryEmail: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'primaryEmail', | ||||
|         label: 'Primary Email', | ||||
|         description: 'Primary Email', | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const additionalEmails: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'additionalEmails', | ||||
|         label: 'Additional Emails', | ||||
|         description: 'Additional Emails', | ||||
|         list: true, | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       return [primaryEmail, additionalEmails]; | ||||
|     } | ||||
|     case FieldMetadataType.LINKS: { | ||||
|       const primaryLinkLabel: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'primaryLinkLabel', | ||||
|         label: 'Primary Link Label', | ||||
|         description: 'Primary Link Label', | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const primaryLinkUrl: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'primaryLinkUrl', | ||||
|         label: 'Primary Link Url', | ||||
|         description: 'Primary Link Url', | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|       }; | ||||
|       const secondaryLinks: NodeField = { | ||||
|         type: FieldMetadataType.TEXT, | ||||
|         name: 'secondaryLinks', | ||||
|         label: 'Secondary Links', | ||||
|         description: 'Secondary Links', | ||||
|         isNullable: true, | ||||
|         defaultValue: null, | ||||
|         placeholder: '{ url: "", label: "" }', | ||||
|         list: true, | ||||
|       }; | ||||
|       return [primaryLinkLabel, primaryLinkUrl, secondaryLinks]; | ||||
|     } | ||||
|     default: | ||||
|       throw new Error(`Unknown nodeField type: ${nodeField.type}`); | ||||
|   } | ||||
| @@ -161,6 +246,9 @@ export const computeInputFields = ( | ||||
|       case FieldMetadataType.FULL_NAME: | ||||
|       case FieldMetadataType.LINK: | ||||
|       case FieldMetadataType.CURRENCY: | ||||
|       case FieldMetadataType.PHONES: | ||||
|       case FieldMetadataType.EMAILS: | ||||
|       case FieldMetadataType.LINKS: | ||||
|       case FieldMetadataType.ADDRESS: | ||||
|         for (const subNodeField of get_subfieldsFromField(nodeField)) { | ||||
|           const field = { | ||||
| @@ -169,12 +257,15 @@ export const computeInputFields = ( | ||||
|             type: getTypeFromFieldMetadataType(subNodeField.type), | ||||
|             helpText: `${nodeField.description}: ${subNodeField.description}`, | ||||
|             required: isFieldRequired(subNodeField), | ||||
|             list: !!subNodeField.list, | ||||
|             placeholder: subNodeField.placeholder, | ||||
|           } as InputField; | ||||
|           result.push(field); | ||||
|         } | ||||
|         break; | ||||
|       case FieldMetadataType.UUID: | ||||
|       case FieldMetadataType.TEXT: | ||||
|       case FieldMetadataType.RICH_TEXT: | ||||
|       case FieldMetadataType.PHONE: | ||||
|       case FieldMetadataType.EMAIL: | ||||
|       case FieldMetadataType.DATE_TIME: | ||||
| @@ -182,6 +273,8 @@ export const computeInputFields = ( | ||||
|       case FieldMetadataType.BOOLEAN: | ||||
|       case FieldMetadataType.NUMBER: | ||||
|       case FieldMetadataType.NUMERIC: | ||||
|       case FieldMetadataType.POSITION: | ||||
|       case FieldMetadataType.ARRAY: | ||||
|       case FieldMetadataType.RATING: { | ||||
|         const nodeFieldType = getTypeFromFieldMetadataType(nodeField.type); | ||||
|         if (!nodeFieldType) { | ||||
| @@ -196,6 +289,7 @@ export const computeInputFields = ( | ||||
|           type: nodeFieldType, | ||||
|           helpText: nodeField.description, | ||||
|           required, | ||||
|           list: getListFromFieldMetadataType(nodeField.type), | ||||
|         }; | ||||
|         result.push(field); | ||||
|         break; | ||||
|   | ||||
| @@ -3,12 +3,14 @@ export type InputData = { [x: string]: any }; | ||||
| export type ObjectData = { id: string } | { [x: string]: any }; | ||||
|  | ||||
| export type NodeField = { | ||||
|   type: string; | ||||
|   type: FieldMetadataType; | ||||
|   name: string; | ||||
|   label: string; | ||||
|   description: string | null; | ||||
|   isNullable: boolean; | ||||
|   defaultValue: object | null; | ||||
|   list?: boolean; | ||||
|   placeholder?: string; | ||||
| }; | ||||
|  | ||||
| export type Node = { | ||||
| @@ -28,26 +30,39 @@ export type InputField = { | ||||
|   type: string; | ||||
|   helpText: string | null; | ||||
|   required: boolean; | ||||
|   list?: boolean; | ||||
|   placeholder?: string; | ||||
| }; | ||||
|  | ||||
| export enum FieldMetadataType { | ||||
|   UUID = 'UUID', | ||||
|   TEXT = 'TEXT', | ||||
|   PHONE = 'PHONE', | ||||
|   PHONES = 'PHONES', | ||||
|   EMAIL = 'EMAIL', | ||||
|   EMAILS = 'EMAILS', | ||||
|   DATE_TIME = 'DATE_TIME', | ||||
|   DATE = 'DATE', | ||||
|   BOOLEAN = 'BOOLEAN', | ||||
|   NUMBER = 'NUMBER', | ||||
|   NUMERIC = 'NUMERIC', | ||||
|   LINK = 'LINK', | ||||
|   LINKS = 'LINKS', | ||||
|   CURRENCY = 'CURRENCY', | ||||
|   FULL_NAME = 'FULL_NAME', | ||||
|   RATING = 'RATING', | ||||
|   SELECT = 'SELECT', | ||||
|   MULTI_SELECT = 'MULTI_SELECT', | ||||
|   RELATION = 'RELATION', | ||||
|   POSITION = 'POSITION', | ||||
|   ADDRESS = 'ADDRESS', | ||||
|   RICH_TEXT = 'RICH_TEXT', | ||||
|   ARRAY = 'ARRAY', | ||||
|  | ||||
|   // Ignored fieldTypes | ||||
|   RELATION = 'RELATION', | ||||
|   RAW_JSON = 'RAW_JSON', | ||||
|   ACTOR = 'ACTOR', | ||||
|   TS_VECTOR = 'TS_VECTOR', | ||||
| } | ||||
|  | ||||
| export type Schema = { | ||||
|   | ||||
| @@ -1,5 +1,17 @@ | ||||
| import { InputData } from '../utils/data.types'; | ||||
|  | ||||
| const OBJECT_SUBFIELD_NAMES = ['secondaryLinks', 'additionalPhones']; | ||||
|  | ||||
| const formatArrayInputData = ( | ||||
|   key: string, | ||||
|   arrayInputData: InputData, | ||||
| ): string => { | ||||
|   if (OBJECT_SUBFIELD_NAMES.includes(key)) { | ||||
|     return `${arrayInputData[key].join('","')}`; | ||||
|   } | ||||
|   return `"${arrayInputData[key].join('","')}"`; | ||||
| }; | ||||
|  | ||||
| const handleQueryParams = (inputData: InputData): string => { | ||||
|   const formattedInputData: InputData = {}; | ||||
|   Object.keys(inputData).forEach((key) => { | ||||
| @@ -17,7 +29,11 @@ const handleQueryParams = (inputData: InputData): string => { | ||||
|   let result = ''; | ||||
|   Object.keys(formattedInputData).forEach((key) => { | ||||
|     let quote = ''; | ||||
|     if (typeof formattedInputData[key] === 'object') { | ||||
|     if (Array.isArray(formattedInputData[key])) { | ||||
|       result = result.concat( | ||||
|         `${key}: [${formatArrayInputData(key, formattedInputData)}], `, | ||||
|       ); | ||||
|     } else if (typeof formattedInputData[key] === 'object') { | ||||
|       result = result.concat( | ||||
|         `${key}: {${handleQueryParams(formattedInputData[key])}}, `, | ||||
|       ); | ||||
|   | ||||
| @@ -9,5 +9,12 @@ | ||||
|     "strict": true, | ||||
|     "esModuleInterop": true, | ||||
|     "skipLibCheck": true | ||||
|   } | ||||
|   }, | ||||
|   "exclude": [ | ||||
|     "**/*.spec.ts", | ||||
|     "**/*.test.ts", | ||||
|     "**/*.spec.tsx", | ||||
|     "**/*.test.tsx", | ||||
|     "jest.config.ts" | ||||
|   ] | ||||
| } | ||||
|   | ||||
| @@ -24321,7 +24321,7 @@ __metadata: | ||||
|   languageName: node | ||||
|   linkType: hard | ||||
| 
 | ||||
| "dotenv@npm:^16.0.0, dotenv@npm:^16.0.3, dotenv@npm:^16.3.0": | ||||
| "dotenv@npm:^16.0.0, dotenv@npm:^16.0.3, dotenv@npm:^16.3.0, dotenv@npm:^16.4.5": | ||||
|   version: 16.4.5 | ||||
|   resolution: "dotenv@npm:16.4.5" | ||||
|   checksum: 10c0/48d92870076832af0418b13acd6e5a5a3e83bb00df690d9812e94b24aff62b88ade955ac99a05501305b8dc8f1b0ee7638b18493deb6fe93d680e5220936292f | ||||
| @@ -43852,6 +43852,7 @@ __metadata: | ||||
|   version: 0.0.0-use.local | ||||
|   resolution: "twenty-zapier@workspace:packages/twenty-zapier" | ||||
|   dependencies: | ||||
|     dotenv: "npm:^16.4.5" | ||||
|     jest: "npm:29.7.0" | ||||
|     rimraf: "npm:^3.0.2" | ||||
|     zapier-platform-cli: "npm:^15.4.1" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 martmull
					martmull