From 5fdb40ca2c8aaffbc73c6c05b6b54d23a82bfacf Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Mon, 24 Nov 2025 17:17:46 -0300 Subject: [PATCH 01/16] Adding DealCloud app and package --- dealcloud/dealcloud.app.mjs | 30 ++++++++++++++++++++++++++++++ dealcloud/package.json | 18 ++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 dealcloud/dealcloud.app.mjs create mode 100644 dealcloud/package.json diff --git a/dealcloud/dealcloud.app.mjs b/dealcloud/dealcloud.app.mjs new file mode 100644 index 0000000000000..9c515f85f14ee --- /dev/null +++ b/dealcloud/dealcloud.app.mjs @@ -0,0 +1,30 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "dealcloud", + propDefinitions: {}, + methods: { + async _makeRequest({ + $ = this, headers, ...args + }) { + const response = await axios($, { + baseURL: `${this.$auth.host_url}/api/rest/v4/`, + headers: { + ...headers, + "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + }, + ...args, + }); + return response.data; + }, + async getEntryTypeFields({ + entryTypeId, ...args + }) { + return this._makeRequest({ + url: `/schema/entrytypes/${entryTypeId}/fields`, + ...args, + }); + }, + }, +}; diff --git a/dealcloud/package.json b/dealcloud/package.json new file mode 100644 index 0000000000000..3f1eff5fd361f --- /dev/null +++ b/dealcloud/package.json @@ -0,0 +1,18 @@ +{ + "name": "@pipedream/dealcloud", + "version": "0.1.1", + "description": "Pipedream DealCloud Components", + "main": "dealcloud.app.mjs", + "keywords": [ + "pipedream", + "dealcloud" + ], + "homepage": "https://pipedream.com/apps/dealcloud", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.1" + } +} From 9485f56d30d9dde111971a67a0bfb6d87140df2f Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 14:18:51 -0300 Subject: [PATCH 02/16] Adding listEntryTypes --- dealcloud/dealcloud.app.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dealcloud/dealcloud.app.mjs b/dealcloud/dealcloud.app.mjs index 9c515f85f14ee..3f5112f1209f0 100644 --- a/dealcloud/dealcloud.app.mjs +++ b/dealcloud/dealcloud.app.mjs @@ -18,6 +18,12 @@ export default { }); return response.data; }, + async listEntryTypes(args = {}) { + return this._makeRequest({ + url: "/schema/entrytypes", + ...args, + }); + }, async getEntryTypeFields({ entryTypeId, ...args }) { From a464c819c8d7ab0008f3a73f45744b570cb5a4d2 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 17:35:33 -0300 Subject: [PATCH 03/16] Adding initial field-to-prop conversion --- components/dealcloud/common/utils.mjs | 58 +++++++++++++++++++ .../dealcloud}/dealcloud.app.mjs | 0 .../dealcloud}/package.json | 0 3 files changed, 58 insertions(+) create mode 100644 components/dealcloud/common/utils.mjs rename {dealcloud => components/dealcloud}/dealcloud.app.mjs (100%) rename {dealcloud => components/dealcloud}/package.json (100%) diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs new file mode 100644 index 0000000000000..e6371fc46374a --- /dev/null +++ b/components/dealcloud/common/utils.mjs @@ -0,0 +1,58 @@ +/** + * Maps DealCloud field type ID to Pipedream prop type + * @param {number} fieldTypeId - The DealCloud field type ID + * @returns {string} The corresponding Pipedream prop type + */ +function mapFieldTypeToPropType(fieldTypeId) { + switch (fieldTypeId) { + case 3: // Number + return "integer"; + case 6: // Boolean + return "boolean"; + case 1: // Text + case 2: // Choice + case 4: // Date + case 5: // Reference + case 7: // User + case 13: // Binary + case 14: // EntryListId + case 15: // Counter + case 16: // Image + case 17: // DataSource + case 18: // Currency + default: + return "string"; + } +} + +/** + * @typedef {Object} DealCloudField + * @property {string} apiName - The API name of the field + * @property {number} fieldType - The type of the field (numeric code) + * @property {boolean} isRequired - Whether the field is required + * @property {boolean} isMoney - Whether the field represents a monetary value + * @property {boolean} isMultiSelect - Whether the field allows multiple selections + * @property {Array} entryLists - List of entry options for the field + * @property {number} systemFieldType - The system field type (numeric code) + * @property {boolean} isKey - Whether the field is a key field + * @property {boolean} isCalculated - Whether the field is calculated + * @property {number} id - The unique identifier of the field + * @property {string} name - The display name of the field + * @property {number} entryListId - The ID of the associated entry list + */ + +/** + * Converts DealCloud fields to Pipedream prop format + * @param {DealCloudField[]} fields - Array of DealCloud field objects + * @returns Object to be returned in dynamic props + */ +export function convertFieldsToProps(fields) { + return fields.reduce((acc, field) => { + acc[field.apiName] = { + label: field.name, + type: mapFieldTypeToPropType(field.fieldType), + description: `Field ID: \`${field.id}\`. Field type: \`${field.fieldType}\``, + }; + return acc; + }, {}); +} diff --git a/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs similarity index 100% rename from dealcloud/dealcloud.app.mjs rename to components/dealcloud/dealcloud.app.mjs diff --git a/dealcloud/package.json b/components/dealcloud/package.json similarity index 100% rename from dealcloud/package.json rename to components/dealcloud/package.json From 7ddafaf09aaeb6521e534e3983db195c73393e07 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 17:36:36 -0300 Subject: [PATCH 04/16] pnpm --- pnpm-lock.yaml | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a89f72da8aa97..25428c8a64970 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2043,8 +2043,7 @@ importers: components/braintree: {} - components/brand_dev: - specifiers: {} + components/brand_dev: {} components/brandblast: {} @@ -3588,8 +3587,7 @@ importers: components/currents_api: {} - components/cursor: - specifiers: {} + components/cursor: {} components/customer_fields: dependencies: @@ -3815,6 +3813,12 @@ importers: specifier: ^3.1.1 version: 3.1.1 + components/dealcloud: + dependencies: + '@pipedream/platform': + specifier: ^3.1.1 + version: 3.1.1 + components/dealmachine: dependencies: '@pipedream/platform': @@ -5669,8 +5673,7 @@ importers: components/funnelcockpit: {} - components/fynk: - specifiers: {} + components/fynk: {} components/gagelist: dependencies: @@ -6736,8 +6739,7 @@ importers: components/helcim: {} - components/helicone: - specifiers: {} + components/helicone: {} components/helium: dependencies: @@ -8649,8 +8651,7 @@ importers: specifier: ^1.6.8 version: 1.6.8 - components/magicalapi: - specifiers: {} + components/magicalapi: {} components/magileads: {} @@ -12280,8 +12281,7 @@ importers: specifier: ^3.1.1 version: 3.1.1 - components/relationcity: - specifiers: {} + components/relationcity: {} components/relavate: dependencies: @@ -14054,8 +14054,7 @@ importers: components/socialkit: {} - components/socket: - specifiers: {} + components/socket: {} components/softledger: {} @@ -15438,8 +15437,7 @@ importers: components/turbohire: {} - components/turbosmtp: - specifiers: {} + components/turbosmtp: {} components/turbot_pipes: dependencies: @@ -15871,8 +15869,7 @@ importers: specifier: ^3.1.1 version: 3.1.1 - components/validemail: - specifiers: {} + components/validemail: {} components/vapi: dependencies: @@ -15976,8 +15973,7 @@ importers: components/verticalresponse: {} - components/veryfi: - specifiers: {} + components/veryfi: {} components/vestaboard: dependencies: @@ -31491,17 +31487,17 @@ packages: superagent@3.8.1: resolution: {integrity: sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==} engines: {node: '>= 4.0'} - deprecated: Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net + deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net superagent@4.1.0: resolution: {integrity: sha512-FT3QLMasz0YyCd4uIi5HNe+3t/onxMyEho7C3PSqmti3Twgy2rXT4fmkTz6wRL6bTF4uzPcfkUCa8u4JWHw8Ag==} engines: {node: '>= 6.0'} - deprecated: Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net + deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net superagent@5.3.1: resolution: {integrity: sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==} engines: {node: '>= 7.0.0'} - deprecated: Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net + deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net supports-color@10.2.2: resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} @@ -39125,7 +39121,6 @@ snapshots: transitivePeerDependencies: - rolldown - rollup - - supports-color '@putout/operator-parens@2.0.0(rolldown@1.0.0-beta.9)(rollup@4.53.2)': dependencies: From dfbe0af39dc06c6cd6725dea69db17899ad6e72d Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 18:38:11 -0300 Subject: [PATCH 05/16] Fetching entries and parsing option-based props --- components/dealcloud/common/constants.mjs | 154 ++++++++++++++++++++++ components/dealcloud/common/utils.mjs | 72 +++++++--- components/dealcloud/dealcloud.app.mjs | 48 ++++++- 3 files changed, 252 insertions(+), 22 deletions(-) create mode 100644 components/dealcloud/common/constants.mjs diff --git a/components/dealcloud/common/constants.mjs b/components/dealcloud/common/constants.mjs new file mode 100644 index 0000000000000..b0fc37cfab801 --- /dev/null +++ b/components/dealcloud/common/constants.mjs @@ -0,0 +1,154 @@ +export const CURRENCY_OPTIONS = [ + "AED", + "AFN", + "ALL", + "AMD", + "ANG", + "AOA", + "ARS", + "AUD", + "AWG", + "AZN", + "BAM", + "BBD", + "BDT", + "BGN", + "BHD", + "BIF", + "BMD", + "BND", + "BOB", + "BRL", + "BSD", + "BTN", + "BWP", + "BYN", + "BZD", + "CAD", + "CDF", + "CHF", + "CLP", + "CNH", + "CNY", + "COP", + "CRC", + "CUC", + "CUP", + "CVE", + "CZK", + "DJF", + "DKK", + "DOP", + "DZD", + "EEK", + "EGP", + "ERN", + "ETB", + "EUR", + "FJD", + "FKP", + "GBP", + "GEL", + "GHS", + "GIP", + "GMD", + "GNF", + "GTQ", + "GYD", + "HKD", + "HNL", + "HRK", + "HTG", + "HUF", + "IDR", + "ILS", + "INR", + "IQD", + "IRR", + "ISK", + "JMD", + "JOD", + "JPY", + "KES", + "KGS", + "KHR", + "KMF", + "KRW", + "KWD", + "KYD", + "KZT", + "LAK", + "LBP", + "LKR", + "LRD", + "LSL", + "LTL", + "LVL", + "LYD", + "MAD", + "MDL", + "MGA", + "MKD", + "MMK", + "MNT", + "MOP", + "MRU", + "MUR", + "MVR", + "MWK", + "MXN", + "MYR", + "MZN", + "NAD", + "NGN", + "NIO", + "NLG", + "NOK", + "NPR", + "NZD", + "OMR", + "PAB", + "PEN", + "PGK", + "PHP", + "PKR", + "PLN", + "PYG", + "QAR", + "RON", + "RSD", + "RUB", + "RWF", + "SAR", + "SBD", + "SCR", + "SDG", + "SEK", + "SGD", + "SLL", + "SRD", + "SYP", + "SZL", + "THB", + "TJS", + "TMT", + "TND", + "TOP", + "TRY", + "TTD", + "TWD", + "TZS", + "UAH", + "UGX", + "USD", + "UYU", + "UZS", + "VND", + "VUV", + "WST", + "XAF", + "XCD", + "XOF", + "ZAR", + "ZMW", +]; diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs index e6371fc46374a..e2afe93005ce4 100644 --- a/components/dealcloud/common/utils.mjs +++ b/components/dealcloud/common/utils.mjs @@ -1,27 +1,39 @@ +import { CURRENCY_OPTIONS } from "./constants.mjs"; + +const FIELD_TYPES = { + TEXT: 1, + CHOICE: 2, + NUMBER: 3, + DATE: 4, + REFERENCE: 5, + BOOLEAN: 6, + USER: 7, + BINARY: 13, + ENTRY_LIST_ID: 14, + COUNTER: 15, + IMAGE: 16, + DATA_SOURCE: 17, + CURRENCY: 18, +}; + /** * Maps DealCloud field type ID to Pipedream prop type * @param {number} fieldTypeId - The DealCloud field type ID + * @param {boolean} isArray - Whether the field is an array * @returns {string} The corresponding Pipedream prop type */ -function mapFieldTypeToPropType(fieldTypeId) { +function mapFieldTypeToPropType(fieldTypeId, isArray) { switch (fieldTypeId) { - case 3: // Number - return "integer"; - case 6: // Boolean + case FIELD_TYPES.NUMBER: + return isArray + ? "integer[]" + : "integer"; + case FIELD_TYPES.BOOLEAN: return "boolean"; - case 1: // Text - case 2: // Choice - case 4: // Date - case 5: // Reference - case 7: // User - case 13: // Binary - case 14: // EntryListId - case 15: // Counter - case 16: // Image - case 17: // DataSource - case 18: // Currency default: - return "string"; + return isArray + ? "string[]" + : "string"; } } @@ -47,12 +59,36 @@ function mapFieldTypeToPropType(fieldTypeId) { * @returns Object to be returned in dynamic props */ export function convertFieldsToProps(fields) { + console.log("fields: ", JSON.stringify(fields || {})); return fields.reduce((acc, field) => { - acc[field.apiName] = { + const { fieldType } = field; + const prop = { label: field.name, - type: mapFieldTypeToPropType(field.fieldType), + type: mapFieldTypeToPropType(fieldType, field.isMultiSelect), description: `Field ID: \`${field.id}\`. Field type: \`${field.fieldType}\``, }; + + if (fieldType === FIELD_TYPES.CURRENCY) { + prop.options = CURRENCY_OPTIONS; + } + + if (field.entryLists?.length) { + prop.options = async () => { + const results = await this.dealcloud.getAllEntryTypeEntries({ + entryTypeId: field.entryLists[0], + }); + return results.map((entry) => { + const value = entry.EntryId || entry.Id || entry.id; + const label = entry.Name || value; + return { + label, + value, + }; + }); + }; + } + + acc[field.apiName] = prop; return acc; }, {}); } diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index 3f5112f1209f0..a0b98e9214081 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -3,20 +3,52 @@ import { axios } from "@pipedream/platform"; export default { type: "app", app: "dealcloud", - propDefinitions: {}, + propDefinitions: { + entryTypeId: { + type: "integer", + label: "Object ID", + description: "The ID of the object (entry type) to use.", + async options() { + const results = await this.listEntryTypes(); + return results.map(({ + id: value, name: label, + }) => ({ + value, + label, + })); + }, + }, + }, + entryId: { + type: "integer", + label: "Record ID", + description: "The ID of the record (entry) to use.", + async options({ entryTypeId }) { + const results = await this.getAllEntryTypeEntries({ + entryTypeId, + }); + return results.map((entry) => { + const value = entry.EntryId || entry.Id || entry.id; + const label = entry.Name || value; + return { + label, + value, + }; + }); + }, + }, methods: { async _makeRequest({ $ = this, headers, ...args }) { - const response = await axios($, { + return axios($, { baseURL: `${this.$auth.host_url}/api/rest/v4/`, headers: { ...headers, - "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + Authorization: `Bearer ${this.$auth.oauth_access_token}`, }, ...args, }); - return response.data; }, async listEntryTypes(args = {}) { return this._makeRequest({ @@ -32,5 +64,13 @@ export default { ...args, }); }, + async getAllEntryTypeEntries({ + entryTypeId, ...args + }) { + return this._makeRequest({ + url: `data/entrydata/${entryTypeId}/entries`, + ...args, + }); + }, }, }; From 195aede94021090e3d9496693fcf9c131aa7c016 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 18:59:56 -0300 Subject: [PATCH 06/16] adding mocked data for testing --- components/dealcloud/common/mock-data.mjs | 1112 +++++++++++++++++++++ components/dealcloud/dealcloud.app.mjs | 21 + 2 files changed, 1133 insertions(+) create mode 100644 components/dealcloud/common/mock-data.mjs diff --git a/components/dealcloud/common/mock-data.mjs b/components/dealcloud/common/mock-data.mjs new file mode 100644 index 0000000000000..4e1471b1033da --- /dev/null +++ b/components/dealcloud/common/mock-data.mjs @@ -0,0 +1,1112 @@ +/** + * Mock data for DealCloud API endpoints + * Used for testing without actual API access + */ + +/** + * Mock response for GET /schema/entrytypes + * Returns a list of entry types (objects/entities) available in DealCloud + * + * Each entry type represents a different object type like Company, Contact, Deal, etc. + */ +export const mockEntryTypes = [ + { + id: 1, + name: "Company", + description: "Companies and organizations", + isActive: true, + isSystem: false, + iconName: "building", + pluralName: "Companies", + }, + { + id: 2, + name: "Contact", + description: "Individual contacts and people", + isActive: true, + isSystem: false, + iconName: "user", + pluralName: "Contacts", + }, + { + id: 3, + name: "Deal", + description: "Investment deals and opportunities", + isActive: true, + isSystem: false, + iconName: "handshake", + pluralName: "Deals", + }, + { + id: 4, + name: "Fund", + description: "Investment funds", + isActive: true, + isSystem: false, + iconName: "piggy-bank", + pluralName: "Funds", + }, + { + id: 5, + name: "Portfolio Company", + description: "Companies in the portfolio", + isActive: true, + isSystem: false, + iconName: "briefcase", + pluralName: "Portfolio Companies", + }, +]; + +/** + * Mock response for GET /schema/entrytypes/{entryTypeId}/fields + * Returns field definitions for a specific entry type + * + * Field types: + * 1 = TEXT + * 2 = CHOICE (dropdown/select) + * 3 = NUMBER + * 4 = DATE + * 5 = REFERENCE (relationship to another entry type) + * 6 = BOOLEAN + * 7 = USER + * 13 = BINARY + * 14 = ENTRY_LIST_ID + * 15 = COUNTER + * 16 = IMAGE + * 17 = DATA_SOURCE + * 18 = CURRENCY + */ +export const mockEntryTypeFields = { + // Company fields (entryTypeId: 1) + 1: [ + { + id: 101, + name: "Company Name", + apiName: "CompanyName", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: true, + isKey: true, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "The legal name of the company", + maxLength: 255, + }, + { + id: 102, + name: "Industry", + apiName: "Industry", + fieldType: 2, // CHOICE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 10, + ], // References entry list ID 10 + entryListId: 10, + description: "The industry sector of the company", + }, + { + id: 103, + name: "Revenue", + apiName: "Revenue", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: true, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Annual revenue", + decimalPlaces: 2, + }, + { + id: 104, + name: "Founded Date", + apiName: "FoundedDate", + fieldType: 4, // DATE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Date the company was founded", + }, + { + id: 105, + name: "Primary Contact", + apiName: "PrimaryContact", + fieldType: 5, // REFERENCE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 2, + ], // References Contact entry type + entryListId: 2, + description: "Primary contact person at the company", + }, + { + id: 106, + name: "Is Active", + apiName: "IsActive", + fieldType: 6, // BOOLEAN + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Whether the company is actively being tracked", + }, + { + id: 107, + name: "Account Manager", + apiName: "AccountManager", + fieldType: 7, // USER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "User responsible for managing this company", + }, + { + id: 108, + name: "Tags", + apiName: "Tags", + fieldType: 2, // CHOICE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: true, // Multi-select field + entryLists: [ + 11, + ], + entryListId: 11, + description: "Tags for categorizing the company", + }, + { + id: 109, + name: "Valuation Currency", + apiName: "ValuationCurrency", + fieldType: 18, // CURRENCY + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Currency for company valuation", + }, + { + id: 110, + name: "Employee Count", + apiName: "EmployeeCount", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Number of employees", + decimalPlaces: 0, + }, + ], + // Contact fields (entryTypeId: 2) + 2: [ + { + id: 201, + name: "Full Name", + apiName: "FullName", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: true, + isKey: true, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Contact's full name", + maxLength: 255, + }, + { + id: 202, + name: "Email", + apiName: "Email", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Contact's email address", + maxLength: 255, + }, + { + id: 203, + name: "Phone", + apiName: "Phone", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Contact's phone number", + maxLength: 50, + }, + { + id: 204, + name: "Company", + apiName: "Company", + fieldType: 5, // REFERENCE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 1, + ], // References Company entry type + entryListId: 1, + description: "Company the contact works for", + }, + { + id: 205, + name: "Title", + apiName: "Title", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Job title", + maxLength: 255, + }, + { + id: 206, + name: "Contact Type", + apiName: "ContactType", + fieldType: 2, // CHOICE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 12, + ], + entryListId: 12, + description: "Type of contact", + }, + { + id: 207, + name: "Is Primary", + apiName: "IsPrimary", + fieldType: 6, // BOOLEAN + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Whether this is a primary contact", + }, + ], + // Deal fields (entryTypeId: 3) + 3: [ + { + id: 301, + name: "Deal Name", + apiName: "DealName", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: true, + isKey: true, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Name of the deal", + maxLength: 255, + }, + { + id: 302, + name: "Deal Amount", + apiName: "DealAmount", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: true, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Total deal value", + decimalPlaces: 2, + }, + { + id: 303, + name: "Deal Stage", + apiName: "DealStage", + fieldType: 2, // CHOICE + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 13, + ], + entryListId: 13, + description: "Current stage of the deal", + }, + { + id: 304, + name: "Target Company", + apiName: "TargetCompany", + fieldType: 5, // REFERENCE + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 1, + ], + entryListId: 1, + description: "Company being acquired or invested in", + }, + { + id: 305, + name: "Close Date", + apiName: "CloseDate", + fieldType: 4, // DATE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Expected or actual close date", + }, + { + id: 306, + name: "Deal Currency", + apiName: "DealCurrency", + fieldType: 18, // CURRENCY + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Currency for the deal", + }, + { + id: 307, + name: "Deal Team", + apiName: "DealTeam", + fieldType: 7, // USER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: true, + entryLists: [], + entryListId: null, + description: "Team members working on the deal", + }, + { + id: 308, + name: "Probability", + apiName: "Probability", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Probability of deal closing (0-100)", + decimalPlaces: 0, + }, + ], + // Fund fields (entryTypeId: 4) + 4: [ + { + id: 401, + name: "Fund Name", + apiName: "FundName", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: true, + isKey: true, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Name of the fund", + maxLength: 255, + }, + { + id: 402, + name: "Fund Size", + apiName: "FundSize", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: true, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Total fund size", + decimalPlaces: 2, + }, + { + id: 403, + name: "Fund Currency", + apiName: "FundCurrency", + fieldType: 18, // CURRENCY + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Currency of the fund", + }, + { + id: 404, + name: "Vintage Year", + apiName: "VintageYear", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: true, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Year the fund was established", + decimalPlaces: 0, + }, + { + id: 405, + name: "Fund Status", + apiName: "FundStatus", + fieldType: 2, // CHOICE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 14, + ], + entryListId: 14, + description: "Current status of the fund", + }, + { + id: 406, + name: "Fund Manager", + apiName: "FundManager", + fieldType: 7, // USER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Primary fund manager", + }, + ], + // Portfolio Company fields (entryTypeId: 5) + 5: [ + { + id: 501, + name: "Portfolio Company Name", + apiName: "PortfolioCompanyName", + fieldType: 1, // TEXT + systemFieldType: 0, + isRequired: true, + isKey: true, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Name of the portfolio company", + maxLength: 255, + }, + { + id: 502, + name: "Investment Amount", + apiName: "InvestmentAmount", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: true, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Total investment amount", + decimalPlaces: 2, + }, + { + id: 503, + name: "Investment Date", + apiName: "InvestmentDate", + fieldType: 4, // DATE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Date of initial investment", + }, + { + id: 504, + name: "Ownership Percentage", + apiName: "OwnershipPercentage", + fieldType: 3, // NUMBER + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Percentage ownership", + decimalPlaces: 2, + }, + { + id: 505, + name: "Related Fund", + apiName: "RelatedFund", + fieldType: 5, // REFERENCE + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [ + 4, + ], + entryListId: 4, + description: "Fund that made the investment", + }, + { + id: 506, + name: "Board Representation", + apiName: "BoardRepresentation", + fieldType: 6, // BOOLEAN + systemFieldType: 0, + isRequired: false, + isKey: false, + isCalculated: false, + isMoney: false, + isMultiSelect: false, + entryLists: [], + entryListId: null, + description: "Whether we have board representation", + }, + ], +}; + +/** + * Mock response for GET data/entrydata/{entryTypeId}/entries + * Returns actual entry (record) data for a specific entry type + * + * Note: The response structure includes various field name formats: + * - EntryId, Id, or id for the record ID + * - Name for the display name + * - Field values using the apiName from the field definitions + */ +export const mockEntries = { + // Company entries (entryTypeId: 1) + 1: [ + { + EntryId: 1001, + Id: 1001, + Name: "Acme Corporation", + CompanyName: "Acme Corporation", + Industry: 101, // References entry list item + Revenue: 50000000.00, + FoundedDate: "2010-03-15T00:00:00Z", + PrimaryContact: 2001, // References Contact with ID 2001 + IsActive: true, + AccountManager: 5001, // User ID + Tags: [ + 111, + 112, + ], // Multiple entry list items + ValuationCurrency: "USD", + EmployeeCount: 250, + CreatedDate: "2023-01-10T14:30:00Z", + ModifiedDate: "2024-11-20T09:15:00Z", + }, + { + EntryId: 1002, + Id: 1002, + Name: "TechStart Inc", + CompanyName: "TechStart Inc", + Industry: 102, + Revenue: 15000000.00, + FoundedDate: "2018-07-22T00:00:00Z", + PrimaryContact: 2002, + IsActive: true, + AccountManager: 5002, + Tags: [ + 111, + ], + ValuationCurrency: "USD", + EmployeeCount: 75, + CreatedDate: "2023-02-15T10:20:00Z", + ModifiedDate: "2024-11-18T16:45:00Z", + }, + { + EntryId: 1003, + Id: 1003, + Name: "Global Ventures Ltd", + CompanyName: "Global Ventures Ltd", + Industry: 103, + Revenue: 125000000.00, + FoundedDate: "2005-11-08T00:00:00Z", + PrimaryContact: 2003, + IsActive: true, + AccountManager: 5001, + Tags: [ + 112, + 113, + ], + ValuationCurrency: "EUR", + EmployeeCount: 500, + CreatedDate: "2023-03-20T11:00:00Z", + ModifiedDate: "2024-11-22T13:30:00Z", + }, + ], + // Contact entries (entryTypeId: 2) + 2: [ + { + EntryId: 2001, + Id: 2001, + Name: "John Smith", + FullName: "John Smith", + Email: "john.smith@acme.com", + Phone: "+1-555-0101", + Company: 1001, // References Company + Title: "CEO", + ContactType: 121, + IsPrimary: true, + CreatedDate: "2023-01-10T14:35:00Z", + ModifiedDate: "2024-10-15T08:20:00Z", + }, + { + EntryId: 2002, + Id: 2002, + Name: "Sarah Johnson", + FullName: "Sarah Johnson", + Email: "sarah.j@techstart.io", + Phone: "+1-555-0102", + Company: 1002, + Title: "Founder & CTO", + ContactType: 121, + IsPrimary: true, + CreatedDate: "2023-02-15T10:25:00Z", + ModifiedDate: "2024-11-10T14:15:00Z", + }, + { + EntryId: 2003, + Id: 2003, + Name: "Michael Chen", + FullName: "Michael Chen", + Email: "m.chen@globalventures.com", + Phone: "+44-20-5555-0103", + Company: 1003, + Title: "Managing Director", + ContactType: 121, + IsPrimary: true, + CreatedDate: "2023-03-20T11:05:00Z", + ModifiedDate: "2024-11-15T10:00:00Z", + }, + { + EntryId: 2004, + Id: 2004, + Name: "Emily Rodriguez", + FullName: "Emily Rodriguez", + Email: "emily.r@acme.com", + Phone: "+1-555-0104", + Company: 1001, + Title: "CFO", + ContactType: 122, + IsPrimary: false, + CreatedDate: "2023-04-05T09:30:00Z", + ModifiedDate: "2024-09-20T16:45:00Z", + }, + ], + // Deal entries (entryTypeId: 3) + 3: [ + { + EntryId: 3001, + Id: 3001, + Name: "Series A - TechStart", + DealName: "Series A - TechStart", + DealAmount: 10000000.00, + DealStage: 131, // Entry list item for stage + TargetCompany: 1002, + CloseDate: "2024-12-31T00:00:00Z", + DealCurrency: "USD", + DealTeam: [ + 5001, + 5002, + ], + Probability: 75, + CreatedDate: "2024-06-01T10:00:00Z", + ModifiedDate: "2024-11-20T15:30:00Z", + }, + { + EntryId: 3002, + Id: 3002, + Name: "Acquisition - Acme Corp", + DealName: "Acquisition - Acme Corp", + DealAmount: 75000000.00, + DealStage: 132, + TargetCompany: 1001, + CloseDate: "2025-03-15T00:00:00Z", + DealCurrency: "USD", + DealTeam: [ + 5001, + 5003, + ], + Probability: 60, + CreatedDate: "2024-08-10T14:20:00Z", + ModifiedDate: "2024-11-23T11:15:00Z", + }, + { + EntryId: 3003, + Id: 3003, + Name: "Growth Investment - Global Ventures", + DealName: "Growth Investment - Global Ventures", + DealAmount: 25000000.00, + DealStage: 133, + TargetCompany: 1003, + CloseDate: "2024-11-30T00:00:00Z", + DealCurrency: "EUR", + DealTeam: [ + 5002, + ], + Probability: 90, + CreatedDate: "2024-05-15T09:45:00Z", + ModifiedDate: "2024-11-24T08:00:00Z", + }, + ], + // Fund entries (entryTypeId: 4) + 4: [ + { + EntryId: 4001, + Id: 4001, + Name: "Growth Fund I", + FundName: "Growth Fund I", + FundSize: 500000000.00, + FundCurrency: "USD", + VintageYear: 2020, + FundStatus: 141, + FundManager: 5001, + CreatedDate: "2020-01-15T10:00:00Z", + ModifiedDate: "2024-10-01T14:30:00Z", + }, + { + EntryId: 4002, + Id: 4002, + Name: "Venture Fund II", + FundName: "Venture Fund II", + FundSize: 750000000.00, + FundCurrency: "USD", + VintageYear: 2022, + FundStatus: 141, + FundManager: 5002, + CreatedDate: "2022-03-01T09:00:00Z", + ModifiedDate: "2024-11-15T11:20:00Z", + }, + { + EntryId: 4003, + Id: 4003, + Name: "European Opportunities Fund", + FundName: "European Opportunities Fund", + FundSize: 300000000.00, + FundCurrency: "EUR", + VintageYear: 2023, + FundStatus: 142, + FundManager: 5003, + CreatedDate: "2023-06-01T08:30:00Z", + ModifiedDate: "2024-11-20T10:00:00Z", + }, + ], + // Portfolio Company entries (entryTypeId: 5) + 5: [ + { + EntryId: 5001, + Id: 5001, + Name: "TechStart Inc", + PortfolioCompanyName: "TechStart Inc", + InvestmentAmount: 8000000.00, + InvestmentDate: "2023-09-15T00:00:00Z", + OwnershipPercentage: 15.5, + RelatedFund: 4001, + BoardRepresentation: true, + CreatedDate: "2023-09-15T14:00:00Z", + ModifiedDate: "2024-11-18T09:30:00Z", + }, + { + EntryId: 5002, + Id: 5002, + Name: "DataFlow Systems", + PortfolioCompanyName: "DataFlow Systems", + InvestmentAmount: 12000000.00, + InvestmentDate: "2022-11-20T00:00:00Z", + OwnershipPercentage: 22.3, + RelatedFund: 4002, + BoardRepresentation: true, + CreatedDate: "2022-11-20T10:15:00Z", + ModifiedDate: "2024-11-10T15:45:00Z", + }, + { + EntryId: 5003, + Id: 5003, + Name: "CloudScale Ltd", + PortfolioCompanyName: "CloudScale Ltd", + InvestmentAmount: 5000000.00, + InvestmentDate: "2024-02-10T00:00:00Z", + OwnershipPercentage: 10.0, + RelatedFund: 4003, + BoardRepresentation: false, + CreatedDate: "2024-02-10T11:30:00Z", + ModifiedDate: "2024-11-22T14:20:00Z", + }, + ], + // Entry list items (for dropdown/choice fields) + // Industry options (entryListId: 10) + 10: [ + { + EntryId: 101, + Id: 101, + Name: "Technology", + }, + { + EntryId: 102, + Id: 102, + Name: "Healthcare", + }, + { + EntryId: 103, + Id: 103, + Name: "Financial Services", + }, + { + EntryId: 104, + Id: 104, + Name: "Manufacturing", + }, + { + EntryId: 105, + Id: 105, + Name: "Retail", + }, + ], + // Tags options (entryListId: 11) + 11: [ + { + EntryId: 111, + Id: 111, + Name: "High Priority", + }, + { + EntryId: 112, + Id: 112, + Name: "Strategic", + }, + { + EntryId: 113, + Id: 113, + Name: "International", + }, + { + EntryId: 114, + Id: 114, + Name: "Early Stage", + }, + ], + // Contact Type options (entryListId: 12) + 12: [ + { + EntryId: 121, + Id: 121, + Name: "Executive", + }, + { + EntryId: 122, + Id: 122, + Name: "Finance", + }, + { + EntryId: 123, + Id: 123, + Name: "Operations", + }, + { + EntryId: 124, + Id: 124, + Name: "Legal", + }, + ], + // Deal Stage options (entryListId: 13) + 13: [ + { + EntryId: 131, + Id: 131, + Name: "Prospecting", + }, + { + EntryId: 132, + Id: 132, + Name: "Due Diligence", + }, + { + EntryId: 133, + Id: 133, + Name: "Negotiation", + }, + { + EntryId: 134, + Id: 134, + Name: "Closed Won", + }, + { + EntryId: 135, + Id: 135, + Name: "Closed Lost", + }, + ], + // Fund Status options (entryListId: 14) + 14: [ + { + EntryId: 141, + Id: 141, + Name: "Active", + }, + { + EntryId: 142, + Id: 142, + Name: "Fundraising", + }, + { + EntryId: 143, + Id: 143, + Name: "Closed", + }, + { + EntryId: 144, + Id: 144, + Name: "Liquidated", + }, + ], +}; + +/** + * Helper function to get mock data based on endpoint + * @param {string} endpoint - The API endpoint being called + * @param {object} params - Parameters for the endpoint (e.g., entryTypeId) + * @returns {any} The appropriate mock data + */ +export function getMockData(endpoint, params = {}) { + // GET /schema/entrytypes + if (endpoint === "/schema/entrytypes") { + return mockEntryTypes; + } + + // GET /schema/entrytypes/{entryTypeId}/fields + if (endpoint.match(/^\/schema\/entrytypes\/\d+\/fields$/)) { + const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[3]); + return mockEntryTypeFields[entryTypeId] || []; + } + + // GET data/entrydata/{entryTypeId}/entries + if (endpoint.match(/^data\/entrydata\/\d+\/entries$/)) { + const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[2]); + return mockEntries[entryTypeId] || []; + } + + // Default: return empty array + return []; +} + diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index a0b98e9214081..8eb8fd366b5d5 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -1,4 +1,5 @@ import { axios } from "@pipedream/platform"; +import { getMockData } from "./common/mock-data.mjs"; export default { type: "app", @@ -38,6 +39,13 @@ export default { }, }, methods: { + /** + * Set this to true to use mock data instead of making real API requests + * Useful for testing without API access + */ + _useMockData() { + return true; + }, async _makeRequest({ $ = this, headers, ...args }) { @@ -51,6 +59,9 @@ export default { }); }, async listEntryTypes(args = {}) { + if (this._useMockData()) { + return getMockData("/schema/entrytypes"); + } return this._makeRequest({ url: "/schema/entrytypes", ...args, @@ -59,6 +70,11 @@ export default { async getEntryTypeFields({ entryTypeId, ...args }) { + if (this._useMockData()) { + return getMockData(`/schema/entrytypes/${entryTypeId}/fields`, { + entryTypeId, + }); + } return this._makeRequest({ url: `/schema/entrytypes/${entryTypeId}/fields`, ...args, @@ -67,6 +83,11 @@ export default { async getAllEntryTypeEntries({ entryTypeId, ...args }) { + if (this._useMockData()) { + return getMockData(`data/entrydata/${entryTypeId}/entries`, { + entryTypeId, + }); + } return this._makeRequest({ url: `data/entrydata/${entryTypeId}/entries`, ...args, From 8db8deebf2bd01e5ae5608f34b2f09325af4bd5e Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 20:08:32 -0300 Subject: [PATCH 07/16] Adding 'get records' and 'delete records' actions --- .../actions/delete-records/delete-records.mjs | 51 ++++++++++++++ .../actions/get-records/get-records.mjs | 55 +++++++++++++++ components/dealcloud/common/utils.mjs | 11 +++ components/dealcloud/dealcloud.app.mjs | 69 ++++++++++++++----- 4 files changed, 169 insertions(+), 17 deletions(-) create mode 100644 components/dealcloud/actions/delete-records/delete-records.mjs create mode 100644 components/dealcloud/actions/get-records/get-records.mjs diff --git a/components/dealcloud/actions/delete-records/delete-records.mjs b/components/dealcloud/actions/delete-records/delete-records.mjs new file mode 100644 index 0000000000000..3c3c7fa1c4486 --- /dev/null +++ b/components/dealcloud/actions/delete-records/delete-records.mjs @@ -0,0 +1,51 @@ +import { checkIdArray } from "../../common/utils.mjs"; +import app from "../../dealcloud.app.mjs"; + +export default { + key: "dealcloud-delete-records", + name: "Delete Record(s)", + description: "Deletes one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/delete)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: true, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + entryTypeId: { + propDefinition: [ + app, + "entryTypeId", + ], + }, + entryIds: { + propDefinition: [ + app, + "entryId", + ({ entryTypeId }) => ({ + entryTypeId, + }), + ], + type: "integer[]", + label: "Record ID(s)", + description: "The ID(s) of one or more records (entries) to delete.", + }, + }, + async run({ $ }) { + const entryIds = checkIdArray(this.entryIds); + const response = await this.app.deleteEntry({ + $, + entryTypeId: this.entryTypeId, + data: entryIds, + }); + + const count = entryIds.length; + $.export("$summary", `Successfully deleted ${count} record${count === 1 + ? "" + : "s"}`); + return response; + }, +}; + diff --git a/components/dealcloud/actions/get-records/get-records.mjs b/components/dealcloud/actions/get-records/get-records.mjs new file mode 100644 index 0000000000000..ada81428ce73c --- /dev/null +++ b/components/dealcloud/actions/get-records/get-records.mjs @@ -0,0 +1,55 @@ +import { checkIdArray } from "../../common/utils.mjs"; +import dealcloud from "../../dealcloud.app.mjs"; + +export default { + key: "dealcloud-get-records", + name: "Get Record(s)", + description: "Retrieves one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/rows/get)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + dealcloud, + entryTypeId: { + propDefinition: [ + dealcloud, + "entryTypeId", + ], + }, + entryIds: { + propDefinition: [ + dealcloud, + "entryId", + ({ entryTypeId }) => ({ + entryTypeId, + }), + ], + type: "integer[]", + label: "Record ID(s)", + description: "The ID(s) of one or more records (entries) to retrieve.", + }, + }, + async run({ $ }) { + const entryIds = checkIdArray(this.entryIds); + const response = await this.dealcloud.queryEntries({ + $, + entryTypeId: this.entryTypeId, + params: { + query: `{entryid: {$in:[${entryIds.join()}]}}`, + resolveReferenceUrls: true, + wrapIntoArrays: true, + }, + }); + + const count = entryIds.length; + $.export("$summary", `Successfully retrieved ${count} record${count === 1 + ? "" + : "s"}`); + return response; + }, +}; + diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs index e2afe93005ce4..86a95fb03bc57 100644 --- a/components/dealcloud/common/utils.mjs +++ b/components/dealcloud/common/utils.mjs @@ -1,5 +1,16 @@ +import { ConfigurationError } from "@pipedream/platform"; import { CURRENCY_OPTIONS } from "./constants.mjs"; +export function checkIdArray(value) { + if (typeof value === "string") { + return value.split(","); + } + if (Array.isArray(value)) { + return value; + } + throw new ConfigurationError("Invalid ID array input: " + JSON.stringify(value)); +} + const FIELD_TYPES = { TEXT: 1, CHOICE: 2, diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index 8eb8fd366b5d5..376e868c8150d 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -19,23 +19,23 @@ export default { })); }, }, - }, - entryId: { - type: "integer", - label: "Record ID", - description: "The ID of the record (entry) to use.", - async options({ entryTypeId }) { - const results = await this.getAllEntryTypeEntries({ - entryTypeId, - }); - return results.map((entry) => { - const value = entry.EntryId || entry.Id || entry.id; - const label = entry.Name || value; - return { - label, - value, - }; - }); + entryId: { + type: "integer", + label: "Record ID", + description: "The ID of the record (entry) to use.", + async options({ entryTypeId }) { + const results = await this.getAllEntryTypeEntries({ + entryTypeId, + }); + return results.map((entry) => { + const value = entry.EntryId || entry.Id || entry.id; + const label = entry.Name || value; + return { + label, + value, + }; + }); + }, }, }, methods: { @@ -93,5 +93,40 @@ export default { ...args, }); }, + async queryEntries({ + entryTypeId, ...args + }) { + return this._makeRequest({ + url: `data/entrydata/rows/${entryTypeId}`, + ...args, + }); + }, + async createEntry({ + entryTypeId, ...args + }) { + return this._makeRequest({ + url: `data/entrydata/${entryTypeId}`, + method: "POST", + ...args, + }); + }, + async updateEntry({ + entryTypeId, ...args + }) { + return this._makeRequest({ + url: `data/entrydata/${entryTypeId}`, + method: "PUT", + ...args, + }); + }, + async deleteEntry({ + entryTypeId, ...args + }) { + return this._makeRequest({ + url: `data/entrydata/${entryTypeId}`, + method: "DELETE", + ...args, + }); + }, }, }; From cdebe41e0467c4c057aaaa9b5e931349552f7962 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 20:32:38 -0300 Subject: [PATCH 08/16] Fixing mocked versions of get and delete record --- .../actions/delete-records/delete-records.mjs | 4 +- .../actions/get-records/get-records.mjs | 4 +- components/dealcloud/common/mock-data.mjs | 143 ++++++++++++++++++ components/dealcloud/dealcloud.app.mjs | 24 +++ 4 files changed, 171 insertions(+), 4 deletions(-) diff --git a/components/dealcloud/actions/delete-records/delete-records.mjs b/components/dealcloud/actions/delete-records/delete-records.mjs index 3c3c7fa1c4486..25dc1e621d844 100644 --- a/components/dealcloud/actions/delete-records/delete-records.mjs +++ b/components/dealcloud/actions/delete-records/delete-records.mjs @@ -2,10 +2,10 @@ import { checkIdArray } from "../../common/utils.mjs"; import app from "../../dealcloud.app.mjs"; export default { - key: "dealcloud-delete-records", + key: "slack_v2-delete-records", name: "Delete Record(s)", description: "Deletes one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/delete)", - version: "0.0.1", + version: "0.0.{{ts}}", type: "action", annotations: { destructiveHint: true, diff --git a/components/dealcloud/actions/get-records/get-records.mjs b/components/dealcloud/actions/get-records/get-records.mjs index ada81428ce73c..26be406db2141 100644 --- a/components/dealcloud/actions/get-records/get-records.mjs +++ b/components/dealcloud/actions/get-records/get-records.mjs @@ -2,10 +2,10 @@ import { checkIdArray } from "../../common/utils.mjs"; import dealcloud from "../../dealcloud.app.mjs"; export default { - key: "dealcloud-get-records", + key: "slack_v2-get-records", name: "Get Record(s)", description: "Retrieves one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/rows/get)", - version: "0.0.1", + version: "0.0.{{ts}}", type: "action", annotations: { destructiveHint: false, diff --git a/components/dealcloud/common/mock-data.mjs b/components/dealcloud/common/mock-data.mjs index 4e1471b1033da..488d0d2f61548 100644 --- a/components/dealcloud/common/mock-data.mjs +++ b/components/dealcloud/common/mock-data.mjs @@ -1106,6 +1106,149 @@ export function getMockData(endpoint, params = {}) { return mockEntries[entryTypeId] || []; } + // GET data/entrydata/rows/{entryTypeId} - Query entries with filtering support + if (endpoint.match(/^data\/entrydata\/rows\/\d+$/)) { + const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[3]); + let entries = mockEntries[entryTypeId] || []; + + // Handle query parameter for filtering by IDs + if (params.params?.query) { + const queryStr = params.params.query; + // Parse query like: {entryid: {$in:[1001,1002]}} + const idMatch = queryStr.match(/\$in:\[([^\]]+)\]/); + if (idMatch) { + const requestedIds = idMatch[1].split(",").map((id) => parseInt(id.trim())); + entries = entries.filter((entry) => { + const entryId = entry.EntryId || entry.Id || entry.id; + return requestedIds.includes(entryId); + }); + } + } + + return entries; + } + + // POST data/entrydata - Create entry + if (endpoint === "POST:data/entrydata") { + const { + entryTypeId, data, + } = params; + + // Validate that data is provided + if (!data || typeof data !== "object") { + return { + success: false, + error: "Invalid data provided for entry creation", + }; + } + + const entries = mockEntries[entryTypeId] || []; + // Generate a new ID based on existing entries + const maxId = entries.reduce((max, entry) => { + const id = entry.EntryId || entry.Id || entry.id || 0; + return Math.max(max, id); + }, 0); + const newId = maxId + 1; + + // Return a mock created entry with the new ID + const createdEntry = { + EntryId: newId, + Id: newId, + ...data, + CreatedDate: new Date().toISOString(), + ModifiedDate: new Date().toISOString(), + }; + + return { + success: true, + entry: createdEntry, + message: `Successfully created entry with ID ${newId}`, + }; + } + + // PUT data/entrydata - Update entry + if (endpoint === "PUT:data/entrydata") { + const { + entryTypeId, data, + } = params; + + // Validate that data is provided + if (!data || typeof data !== "object") { + return { + success: false, + error: "Invalid data provided for entry update", + }; + } + + // Extract entry ID from data + const entryId = data?.EntryId || data?.Id || data?.id; + + // Validate that an ID is provided + if (!entryId) { + return { + success: false, + error: "Entry ID is required for update operation", + }; + } + + // Check if entry exists in mock data + const entries = mockEntries[entryTypeId] || []; + const existingEntry = entries.find((entry) => { + const id = entry.EntryId || entry.Id || entry.id; + return id === entryId; + }); + + // Return a mock updated entry + const updatedEntry = { + EntryId: entryId, + Id: entryId, + ...data, + ModifiedDate: new Date().toISOString(), + }; + + return { + success: true, + entry: updatedEntry, + message: `Successfully updated entry with ID ${entryId}`, + existed: !!existingEntry, + }; + } + + // DELETE data/entrydata - Delete entry + if (endpoint === "DELETE:data/entrydata") { + const { data } = params; + + // Handle both single ID and array of IDs + let entryIds; + if (Array.isArray(data)) { + entryIds = data; + } else if (typeof data === "object") { + const entryId = data?.EntryId || data?.Id || data?.id; + entryIds = entryId + ? [ + entryId, + ] + : []; + } else { + entryIds = [ + data, + ]; + } + + // Return a mock success response + const count = entryIds.length; + return { + success: true, + deletedIds: entryIds, + count, + message: `Successfully deleted ${count} entr${count === 1 + ? "y" + : "ies"}: ID${count === 1 + ? "" + : "s"} ${entryIds.join(", ")}`, + }; + } + // Default: return empty array return []; } diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index 376e868c8150d..ee8f0ed1dcd11 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -96,6 +96,12 @@ export default { async queryEntries({ entryTypeId, ...args }) { + if (this._useMockData()) { + return getMockData(`data/entrydata/rows/${entryTypeId}`, { + entryTypeId, + params: args.params, + }); + } return this._makeRequest({ url: `data/entrydata/rows/${entryTypeId}`, ...args, @@ -104,6 +110,12 @@ export default { async createEntry({ entryTypeId, ...args }) { + if (this._useMockData()) { + return getMockData("POST:data/entrydata", { + entryTypeId, + data: args.data, + }); + } return this._makeRequest({ url: `data/entrydata/${entryTypeId}`, method: "POST", @@ -113,6 +125,12 @@ export default { async updateEntry({ entryTypeId, ...args }) { + if (this._useMockData()) { + return getMockData("PUT:data/entrydata", { + entryTypeId, + data: args.data, + }); + } return this._makeRequest({ url: `data/entrydata/${entryTypeId}`, method: "PUT", @@ -122,6 +140,12 @@ export default { async deleteEntry({ entryTypeId, ...args }) { + if (this._useMockData()) { + return getMockData("DELETE:data/entrydata", { + entryTypeId, + data: args.data, + }); + } return this._makeRequest({ url: `data/entrydata/${entryTypeId}`, method: "DELETE", From 33b6e61b438d1668e68072745504bc7c3fc96601 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 20:56:17 -0300 Subject: [PATCH 09/16] 'Create Record' action and basic stuff --- .../actions/create-record/create-record.mjs | 69 +++++++++++++++++++ components/dealcloud/common/utils.mjs | 2 +- components/dealcloud/dealcloud.app.mjs | 35 ++++------ 3 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 components/dealcloud/actions/create-record/create-record.mjs diff --git a/components/dealcloud/actions/create-record/create-record.mjs b/components/dealcloud/actions/create-record/create-record.mjs new file mode 100644 index 0000000000000..72198986b42e9 --- /dev/null +++ b/components/dealcloud/actions/create-record/create-record.mjs @@ -0,0 +1,69 @@ +import { convertFieldsToProps } from "../../common/utils.mjs"; +import dealcloud from "../../dealcloud.app.mjs"; + +export default { + key: "slack_v2-create-record", + name: "Create Record", + description: "Creates a new record (entry) in DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/rows/create)", + version: "0.0.{{ts}}", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + dealcloud, + entryTypeId: { + propDefinition: [ + dealcloud, + "entryTypeId", + ], + reloadProps: true, + }, + ignoreNearDups: { + propDefinition: [ + dealcloud, + "ignoreNearDups", + ], + }, + }, + async additionalProps() { + const props = {}; + if (!this.entryTypeId) { + return props; + } + const fields = await this.dealcloud.getEntryTypeFields({ + entryTypeId: this.entryTypeId, + }); + return convertFieldsToProps(fields); + }, + async run({ $ }) { + const { + dealcloud, entryTypeId, ignoreNearDups, ...props + } = this; + const response = await dealcloud.createEntry({ + $, + entryTypeId, + data: { + storeRequests: Object.entries(props).map(([ + key, + value, + ]) => { + const fieldId = key.split("_")[1]; + return { + entryId: -1, + fieldId, + ignoreNearDups, + value, + }; + }), + }, + }); + + $.export("$summary", "Successfully created record"); + // add id to summary when we know the response schema + return response; + }, +}; + diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs index 86a95fb03bc57..08526261d7cc9 100644 --- a/components/dealcloud/common/utils.mjs +++ b/components/dealcloud/common/utils.mjs @@ -99,7 +99,7 @@ export function convertFieldsToProps(fields) { }; } - acc[field.apiName] = prop; + acc[`field_${field.id}`] = prop; return acc; }, {}); } diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index ee8f0ed1dcd11..eab8f05f0d5a5 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -1,4 +1,4 @@ -import { axios } from "@pipedream/platform"; +// import { axios } from "@pipedream/platform"; import { getMockData } from "./common/mock-data.mjs"; export default { @@ -37,6 +37,13 @@ export default { }); }, }, + ignoreNearDups: { + type: "boolean", + label: "Ignore Near Duplicates", + description: "Whether to ignore near duplicates when creating a record.", + optional: true, + default: false, + }, }, methods: { /** @@ -47,16 +54,18 @@ export default { return true; }, async _makeRequest({ - $ = this, headers, ...args + /*$ = this,*/ headers, ...args }) { - return axios($, { + const config = { baseURL: `${this.$auth.host_url}/api/rest/v4/`, headers: { ...headers, Authorization: `Bearer ${this.$auth.oauth_access_token}`, }, ...args, - }); + }; + return config; // while testing, return the config instead of making the request + // return axios($, config); }, async listEntryTypes(args = {}) { if (this._useMockData()) { @@ -110,12 +119,6 @@ export default { async createEntry({ entryTypeId, ...args }) { - if (this._useMockData()) { - return getMockData("POST:data/entrydata", { - entryTypeId, - data: args.data, - }); - } return this._makeRequest({ url: `data/entrydata/${entryTypeId}`, method: "POST", @@ -125,12 +128,6 @@ export default { async updateEntry({ entryTypeId, ...args }) { - if (this._useMockData()) { - return getMockData("PUT:data/entrydata", { - entryTypeId, - data: args.data, - }); - } return this._makeRequest({ url: `data/entrydata/${entryTypeId}`, method: "PUT", @@ -140,12 +137,6 @@ export default { async deleteEntry({ entryTypeId, ...args }) { - if (this._useMockData()) { - return getMockData("DELETE:data/entrydata", { - entryTypeId, - data: args.data, - }); - } return this._makeRequest({ url: `data/entrydata/${entryTypeId}`, method: "DELETE", From 2abbb3c6eacc311e2c2ecbf63316404d674bea90 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 21:12:43 -0300 Subject: [PATCH 10/16] Removing dynamic options (for now) --- components/dealcloud/common/utils.mjs | 28 ++++++++++++++------------ components/dealcloud/dealcloud.app.mjs | 6 +++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs index 08526261d7cc9..1c3d70bf8a1eb 100644 --- a/components/dealcloud/common/utils.mjs +++ b/components/dealcloud/common/utils.mjs @@ -77,6 +77,7 @@ export function convertFieldsToProps(fields) { label: field.name, type: mapFieldTypeToPropType(fieldType, field.isMultiSelect), description: `Field ID: \`${field.id}\`. Field type: \`${field.fieldType}\``, + optional: !field.isRequired, }; if (fieldType === FIELD_TYPES.CURRENCY) { @@ -84,19 +85,20 @@ export function convertFieldsToProps(fields) { } if (field.entryLists?.length) { - prop.options = async () => { - const results = await this.dealcloud.getAllEntryTypeEntries({ - entryTypeId: field.entryLists[0], - }); - return results.map((entry) => { - const value = entry.EntryId || entry.Id || entry.id; - const label = entry.Name || value; - return { - label, - value, - }; - }); - }; + prop.description = prop.description + ` Entry List ID: \`${field.entryLists[0]}\``; + // prop.options = async () => { + // const results = await this.dealcloud.getAllEntryTypeEntries({ + // entryTypeId: field.entryLists[0], + // }); + // return results.map((entry) => { + // const value = entry.EntryId || entry.Id || entry.id; + // const label = entry.Name || value; + // return { + // label, + // value, + // }; + // }); + // }; } acc[`field_${field.id}`] = prop; diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index eab8f05f0d5a5..ced19a8f69478 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -3,7 +3,7 @@ import { getMockData } from "./common/mock-data.mjs"; export default { type: "app", - app: "dealcloud", + app: "slack_v2", propDefinitions: { entryTypeId: { type: "integer", @@ -54,7 +54,7 @@ export default { return true; }, async _makeRequest({ - /*$ = this,*/ headers, ...args + $ = this, headers, ...args }) { const config = { baseURL: `${this.$auth.host_url}/api/rest/v4/`, @@ -64,7 +64,7 @@ export default { }, ...args, }; - return config; // while testing, return the config instead of making the request + $;return config; // while testing, return the config instead of making the request // return axios($, config); }, async listEntryTypes(args = {}) { From 32c3e57ffb95402c9391089e3ac73ad2821abe8a Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 22:18:00 -0300 Subject: [PATCH 11/16] Adding 'update record' + patches --- .../actions/common/common-create-update.mjs | 57 +++++++++++++++ .../actions/create-record/create-record.mjs | 61 +++++----------- .../actions/delete-records/delete-records.mjs | 2 +- .../actions/update-record/update-record.mjs | 69 +++++++++++++++++++ components/dealcloud/common/utils.mjs | 5 +- components/dealcloud/dealcloud.app.mjs | 2 +- 6 files changed, 147 insertions(+), 49 deletions(-) create mode 100644 components/dealcloud/actions/common/common-create-update.mjs create mode 100644 components/dealcloud/actions/update-record/update-record.mjs diff --git a/components/dealcloud/actions/common/common-create-update.mjs b/components/dealcloud/actions/common/common-create-update.mjs new file mode 100644 index 0000000000000..438f86adbd55f --- /dev/null +++ b/components/dealcloud/actions/common/common-create-update.mjs @@ -0,0 +1,57 @@ +import { convertFieldsToProps } from "../../common/utils.mjs"; +import dealcloud from "../../dealcloud.app.mjs"; + +export default { + methods: { + convertFieldsToProps, + isUpdate() { + return false; + }, + getEntryId() { + return -1; + }, + getRequestData(props) { + return { + storeRequests: Object.entries(props).map(([ + key, + value, + ]) => { + const fieldId = key.split("_")[1]; + return { + entryId: this.getEntryId(), + fieldId, + ignoreNearDups: this.ignoreNearDups, + value, + }; + }), + }; + }, + }, + props: { + dealcloud, + entryTypeId: { + propDefinition: [ + dealcloud, + "entryTypeId", + ], + reloadProps: true, + }, + ignoreNearDups: { + propDefinition: [ + dealcloud, + "ignoreNearDups", + ], + }, + }, + async additionalProps() { + const props = {}; + if (!this.entryTypeId) { + return props; + } + const fields = await this.dealcloud.getEntryTypeFields({ + entryTypeId: this.entryTypeId, + }); + return this.convertFieldsToProps(fields); + }, +}; + diff --git a/components/dealcloud/actions/create-record/create-record.mjs b/components/dealcloud/actions/create-record/create-record.mjs index 72198986b42e9..e1a6289c8d327 100644 --- a/components/dealcloud/actions/create-record/create-record.mjs +++ b/components/dealcloud/actions/create-record/create-record.mjs @@ -1,10 +1,10 @@ -import { convertFieldsToProps } from "../../common/utils.mjs"; -import dealcloud from "../../dealcloud.app.mjs"; +import commonCreateUpdate from "../common/common-create-update.mjs"; export default { - key: "slack_v2-create-record", + ...commonCreateUpdate, + key: "dealcloud-create-record", name: "Create Record", - description: "Creates a new record (entry) in DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/rows/create)", + description: "Creates a new record (entry) in DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/cells/postput)", version: "0.0.{{ts}}", type: "action", annotations: { @@ -12,53 +12,24 @@ export default { openWorldHint: true, readOnlyHint: false, }, - props: { - dealcloud, - entryTypeId: { - propDefinition: [ - dealcloud, - "entryTypeId", - ], - reloadProps: true, - }, - ignoreNearDups: { - propDefinition: [ - dealcloud, - "ignoreNearDups", - ], - }, - }, - async additionalProps() { - const props = {}; - if (!this.entryTypeId) { - return props; - } - const fields = await this.dealcloud.getEntryTypeFields({ - entryTypeId: this.entryTypeId, - }); - return convertFieldsToProps(fields); - }, async run({ $ }) { + /* eslint-disable no-unused-vars */ const { - dealcloud, entryTypeId, ignoreNearDups, ...props + dealcloud, + entryTypeId, + ignoreNearDups, + convertFieldsToProps, + isUpdate, + getEntryId, + getRequestData, + ...props } = this; + /* eslint-enable no-unused-vars */ + const response = await dealcloud.createEntry({ $, entryTypeId, - data: { - storeRequests: Object.entries(props).map(([ - key, - value, - ]) => { - const fieldId = key.split("_")[1]; - return { - entryId: -1, - fieldId, - ignoreNearDups, - value, - }; - }), - }, + data: this.getRequestData(props), }); $.export("$summary", "Successfully created record"); diff --git a/components/dealcloud/actions/delete-records/delete-records.mjs b/components/dealcloud/actions/delete-records/delete-records.mjs index 25dc1e621d844..f8bd5d6185fbd 100644 --- a/components/dealcloud/actions/delete-records/delete-records.mjs +++ b/components/dealcloud/actions/delete-records/delete-records.mjs @@ -2,7 +2,7 @@ import { checkIdArray } from "../../common/utils.mjs"; import app from "../../dealcloud.app.mjs"; export default { - key: "slack_v2-delete-records", + key: "dealcloud-delete-records", name: "Delete Record(s)", description: "Deletes one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/delete)", version: "0.0.{{ts}}", diff --git a/components/dealcloud/actions/update-record/update-record.mjs b/components/dealcloud/actions/update-record/update-record.mjs new file mode 100644 index 0000000000000..c32d98d988ad5 --- /dev/null +++ b/components/dealcloud/actions/update-record/update-record.mjs @@ -0,0 +1,69 @@ +import commonCreateUpdate from "../common/common-create-update.mjs"; + +const { + props: { + dealcloud, entryTypeId, ignoreNearDups, + }, +} = commonCreateUpdate; + +export default { + ...commonCreateUpdate, + key: "dealcloud-update-record", + name: "Update Record", + description: "Updates a record (entry) in DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/cells/postput)", + version: "0.0.{{ts}}", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + dealcloud, + entryTypeId, + entryId: { + propDefinition: [ + dealcloud, + "entryId", + ({ entryTypeId }) => ({ + entryTypeId, + }), + ], + }, + ignoreNearDups, + }, + methods: { + ...commonCreateUpdate.methods, + isUpdate() { + return true; + }, + getEntryId() { + return this.entryId; + }, + }, + async run({ $ }) { + /* eslint-disable no-unused-vars */ + const { + dealcloud, + entryTypeId, + entryId, + ignoreNearDups, + convertFieldsToProps, + isUpdate, + getEntryId, + getRequestData, + ...props + } = this; + /* eslint-enable no-unused-vars */ + + const response = await dealcloud.updateEntry({ + $, + entryTypeId, + data: this.getRequestData(props), + }); + + $.export("$summary", "Successfully updated record"); + return response; + }, +}; + diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs index 1c3d70bf8a1eb..42a9ea32be8fa 100644 --- a/components/dealcloud/common/utils.mjs +++ b/components/dealcloud/common/utils.mjs @@ -70,14 +70,15 @@ function mapFieldTypeToPropType(fieldTypeId, isArray) { * @returns Object to be returned in dynamic props */ export function convertFieldsToProps(fields) { - console.log("fields: ", JSON.stringify(fields || {})); return fields.reduce((acc, field) => { const { fieldType } = field; const prop = { label: field.name, type: mapFieldTypeToPropType(fieldType, field.isMultiSelect), description: `Field ID: \`${field.id}\`. Field type: \`${field.fieldType}\``, - optional: !field.isRequired, + optional: this.isUpdate() + ? true + : !field.isRequired, }; if (fieldType === FIELD_TYPES.CURRENCY) { diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index ced19a8f69478..a4f73dabbded4 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -3,7 +3,7 @@ import { getMockData } from "./common/mock-data.mjs"; export default { type: "app", - app: "slack_v2", + app: "dealcloud", propDefinitions: { entryTypeId: { type: "integer", From 60384b9af4c2071e80a01a52a4efee57950ac01d Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 22:37:39 -0300 Subject: [PATCH 12/16] Minor patches --- components/dealcloud/actions/get-records/get-records.mjs | 2 +- components/dealcloud/dealcloud.app.mjs | 2 +- components/dealcloud/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/dealcloud/actions/get-records/get-records.mjs b/components/dealcloud/actions/get-records/get-records.mjs index 26be406db2141..fc31f3e6de3e9 100644 --- a/components/dealcloud/actions/get-records/get-records.mjs +++ b/components/dealcloud/actions/get-records/get-records.mjs @@ -2,7 +2,7 @@ import { checkIdArray } from "../../common/utils.mjs"; import dealcloud from "../../dealcloud.app.mjs"; export default { - key: "slack_v2-get-records", + key: "dealcloud-get-records", name: "Get Record(s)", description: "Retrieves one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/rows/get)", version: "0.0.{{ts}}", diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index a4f73dabbded4..9b30aa124cd7c 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -57,7 +57,7 @@ export default { $ = this, headers, ...args }) { const config = { - baseURL: `${this.$auth.host_url}/api/rest/v4/`, + baseURL: `${this.$auth.host}/api/rest/v4/`, headers: { ...headers, Authorization: `Bearer ${this.$auth.oauth_access_token}`, diff --git a/components/dealcloud/package.json b/components/dealcloud/package.json index 3f1eff5fd361f..fbb640aca692f 100644 --- a/components/dealcloud/package.json +++ b/components/dealcloud/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/dealcloud", - "version": "0.1.1", + "version": "0.1.0", "description": "Pipedream DealCloud Components", "main": "dealcloud.app.mjs", "keywords": [ From 8f405bba02b219ff02e872fb6267282eb08a870b Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 23:05:43 -0300 Subject: [PATCH 13/16] Removing mock data --- components/dealcloud/common/mock-data.mjs | 1255 --------------------- components/dealcloud/dealcloud.app.mjs | 32 +- 2 files changed, 2 insertions(+), 1285 deletions(-) delete mode 100644 components/dealcloud/common/mock-data.mjs diff --git a/components/dealcloud/common/mock-data.mjs b/components/dealcloud/common/mock-data.mjs deleted file mode 100644 index 488d0d2f61548..0000000000000 --- a/components/dealcloud/common/mock-data.mjs +++ /dev/null @@ -1,1255 +0,0 @@ -/** - * Mock data for DealCloud API endpoints - * Used for testing without actual API access - */ - -/** - * Mock response for GET /schema/entrytypes - * Returns a list of entry types (objects/entities) available in DealCloud - * - * Each entry type represents a different object type like Company, Contact, Deal, etc. - */ -export const mockEntryTypes = [ - { - id: 1, - name: "Company", - description: "Companies and organizations", - isActive: true, - isSystem: false, - iconName: "building", - pluralName: "Companies", - }, - { - id: 2, - name: "Contact", - description: "Individual contacts and people", - isActive: true, - isSystem: false, - iconName: "user", - pluralName: "Contacts", - }, - { - id: 3, - name: "Deal", - description: "Investment deals and opportunities", - isActive: true, - isSystem: false, - iconName: "handshake", - pluralName: "Deals", - }, - { - id: 4, - name: "Fund", - description: "Investment funds", - isActive: true, - isSystem: false, - iconName: "piggy-bank", - pluralName: "Funds", - }, - { - id: 5, - name: "Portfolio Company", - description: "Companies in the portfolio", - isActive: true, - isSystem: false, - iconName: "briefcase", - pluralName: "Portfolio Companies", - }, -]; - -/** - * Mock response for GET /schema/entrytypes/{entryTypeId}/fields - * Returns field definitions for a specific entry type - * - * Field types: - * 1 = TEXT - * 2 = CHOICE (dropdown/select) - * 3 = NUMBER - * 4 = DATE - * 5 = REFERENCE (relationship to another entry type) - * 6 = BOOLEAN - * 7 = USER - * 13 = BINARY - * 14 = ENTRY_LIST_ID - * 15 = COUNTER - * 16 = IMAGE - * 17 = DATA_SOURCE - * 18 = CURRENCY - */ -export const mockEntryTypeFields = { - // Company fields (entryTypeId: 1) - 1: [ - { - id: 101, - name: "Company Name", - apiName: "CompanyName", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: true, - isKey: true, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "The legal name of the company", - maxLength: 255, - }, - { - id: 102, - name: "Industry", - apiName: "Industry", - fieldType: 2, // CHOICE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 10, - ], // References entry list ID 10 - entryListId: 10, - description: "The industry sector of the company", - }, - { - id: 103, - name: "Revenue", - apiName: "Revenue", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: true, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Annual revenue", - decimalPlaces: 2, - }, - { - id: 104, - name: "Founded Date", - apiName: "FoundedDate", - fieldType: 4, // DATE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Date the company was founded", - }, - { - id: 105, - name: "Primary Contact", - apiName: "PrimaryContact", - fieldType: 5, // REFERENCE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 2, - ], // References Contact entry type - entryListId: 2, - description: "Primary contact person at the company", - }, - { - id: 106, - name: "Is Active", - apiName: "IsActive", - fieldType: 6, // BOOLEAN - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Whether the company is actively being tracked", - }, - { - id: 107, - name: "Account Manager", - apiName: "AccountManager", - fieldType: 7, // USER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "User responsible for managing this company", - }, - { - id: 108, - name: "Tags", - apiName: "Tags", - fieldType: 2, // CHOICE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: true, // Multi-select field - entryLists: [ - 11, - ], - entryListId: 11, - description: "Tags for categorizing the company", - }, - { - id: 109, - name: "Valuation Currency", - apiName: "ValuationCurrency", - fieldType: 18, // CURRENCY - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Currency for company valuation", - }, - { - id: 110, - name: "Employee Count", - apiName: "EmployeeCount", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Number of employees", - decimalPlaces: 0, - }, - ], - // Contact fields (entryTypeId: 2) - 2: [ - { - id: 201, - name: "Full Name", - apiName: "FullName", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: true, - isKey: true, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Contact's full name", - maxLength: 255, - }, - { - id: 202, - name: "Email", - apiName: "Email", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Contact's email address", - maxLength: 255, - }, - { - id: 203, - name: "Phone", - apiName: "Phone", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Contact's phone number", - maxLength: 50, - }, - { - id: 204, - name: "Company", - apiName: "Company", - fieldType: 5, // REFERENCE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 1, - ], // References Company entry type - entryListId: 1, - description: "Company the contact works for", - }, - { - id: 205, - name: "Title", - apiName: "Title", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Job title", - maxLength: 255, - }, - { - id: 206, - name: "Contact Type", - apiName: "ContactType", - fieldType: 2, // CHOICE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 12, - ], - entryListId: 12, - description: "Type of contact", - }, - { - id: 207, - name: "Is Primary", - apiName: "IsPrimary", - fieldType: 6, // BOOLEAN - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Whether this is a primary contact", - }, - ], - // Deal fields (entryTypeId: 3) - 3: [ - { - id: 301, - name: "Deal Name", - apiName: "DealName", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: true, - isKey: true, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Name of the deal", - maxLength: 255, - }, - { - id: 302, - name: "Deal Amount", - apiName: "DealAmount", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: true, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Total deal value", - decimalPlaces: 2, - }, - { - id: 303, - name: "Deal Stage", - apiName: "DealStage", - fieldType: 2, // CHOICE - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 13, - ], - entryListId: 13, - description: "Current stage of the deal", - }, - { - id: 304, - name: "Target Company", - apiName: "TargetCompany", - fieldType: 5, // REFERENCE - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 1, - ], - entryListId: 1, - description: "Company being acquired or invested in", - }, - { - id: 305, - name: "Close Date", - apiName: "CloseDate", - fieldType: 4, // DATE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Expected or actual close date", - }, - { - id: 306, - name: "Deal Currency", - apiName: "DealCurrency", - fieldType: 18, // CURRENCY - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Currency for the deal", - }, - { - id: 307, - name: "Deal Team", - apiName: "DealTeam", - fieldType: 7, // USER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: true, - entryLists: [], - entryListId: null, - description: "Team members working on the deal", - }, - { - id: 308, - name: "Probability", - apiName: "Probability", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Probability of deal closing (0-100)", - decimalPlaces: 0, - }, - ], - // Fund fields (entryTypeId: 4) - 4: [ - { - id: 401, - name: "Fund Name", - apiName: "FundName", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: true, - isKey: true, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Name of the fund", - maxLength: 255, - }, - { - id: 402, - name: "Fund Size", - apiName: "FundSize", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: true, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Total fund size", - decimalPlaces: 2, - }, - { - id: 403, - name: "Fund Currency", - apiName: "FundCurrency", - fieldType: 18, // CURRENCY - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Currency of the fund", - }, - { - id: 404, - name: "Vintage Year", - apiName: "VintageYear", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: true, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Year the fund was established", - decimalPlaces: 0, - }, - { - id: 405, - name: "Fund Status", - apiName: "FundStatus", - fieldType: 2, // CHOICE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 14, - ], - entryListId: 14, - description: "Current status of the fund", - }, - { - id: 406, - name: "Fund Manager", - apiName: "FundManager", - fieldType: 7, // USER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Primary fund manager", - }, - ], - // Portfolio Company fields (entryTypeId: 5) - 5: [ - { - id: 501, - name: "Portfolio Company Name", - apiName: "PortfolioCompanyName", - fieldType: 1, // TEXT - systemFieldType: 0, - isRequired: true, - isKey: true, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Name of the portfolio company", - maxLength: 255, - }, - { - id: 502, - name: "Investment Amount", - apiName: "InvestmentAmount", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: true, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Total investment amount", - decimalPlaces: 2, - }, - { - id: 503, - name: "Investment Date", - apiName: "InvestmentDate", - fieldType: 4, // DATE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Date of initial investment", - }, - { - id: 504, - name: "Ownership Percentage", - apiName: "OwnershipPercentage", - fieldType: 3, // NUMBER - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Percentage ownership", - decimalPlaces: 2, - }, - { - id: 505, - name: "Related Fund", - apiName: "RelatedFund", - fieldType: 5, // REFERENCE - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [ - 4, - ], - entryListId: 4, - description: "Fund that made the investment", - }, - { - id: 506, - name: "Board Representation", - apiName: "BoardRepresentation", - fieldType: 6, // BOOLEAN - systemFieldType: 0, - isRequired: false, - isKey: false, - isCalculated: false, - isMoney: false, - isMultiSelect: false, - entryLists: [], - entryListId: null, - description: "Whether we have board representation", - }, - ], -}; - -/** - * Mock response for GET data/entrydata/{entryTypeId}/entries - * Returns actual entry (record) data for a specific entry type - * - * Note: The response structure includes various field name formats: - * - EntryId, Id, or id for the record ID - * - Name for the display name - * - Field values using the apiName from the field definitions - */ -export const mockEntries = { - // Company entries (entryTypeId: 1) - 1: [ - { - EntryId: 1001, - Id: 1001, - Name: "Acme Corporation", - CompanyName: "Acme Corporation", - Industry: 101, // References entry list item - Revenue: 50000000.00, - FoundedDate: "2010-03-15T00:00:00Z", - PrimaryContact: 2001, // References Contact with ID 2001 - IsActive: true, - AccountManager: 5001, // User ID - Tags: [ - 111, - 112, - ], // Multiple entry list items - ValuationCurrency: "USD", - EmployeeCount: 250, - CreatedDate: "2023-01-10T14:30:00Z", - ModifiedDate: "2024-11-20T09:15:00Z", - }, - { - EntryId: 1002, - Id: 1002, - Name: "TechStart Inc", - CompanyName: "TechStart Inc", - Industry: 102, - Revenue: 15000000.00, - FoundedDate: "2018-07-22T00:00:00Z", - PrimaryContact: 2002, - IsActive: true, - AccountManager: 5002, - Tags: [ - 111, - ], - ValuationCurrency: "USD", - EmployeeCount: 75, - CreatedDate: "2023-02-15T10:20:00Z", - ModifiedDate: "2024-11-18T16:45:00Z", - }, - { - EntryId: 1003, - Id: 1003, - Name: "Global Ventures Ltd", - CompanyName: "Global Ventures Ltd", - Industry: 103, - Revenue: 125000000.00, - FoundedDate: "2005-11-08T00:00:00Z", - PrimaryContact: 2003, - IsActive: true, - AccountManager: 5001, - Tags: [ - 112, - 113, - ], - ValuationCurrency: "EUR", - EmployeeCount: 500, - CreatedDate: "2023-03-20T11:00:00Z", - ModifiedDate: "2024-11-22T13:30:00Z", - }, - ], - // Contact entries (entryTypeId: 2) - 2: [ - { - EntryId: 2001, - Id: 2001, - Name: "John Smith", - FullName: "John Smith", - Email: "john.smith@acme.com", - Phone: "+1-555-0101", - Company: 1001, // References Company - Title: "CEO", - ContactType: 121, - IsPrimary: true, - CreatedDate: "2023-01-10T14:35:00Z", - ModifiedDate: "2024-10-15T08:20:00Z", - }, - { - EntryId: 2002, - Id: 2002, - Name: "Sarah Johnson", - FullName: "Sarah Johnson", - Email: "sarah.j@techstart.io", - Phone: "+1-555-0102", - Company: 1002, - Title: "Founder & CTO", - ContactType: 121, - IsPrimary: true, - CreatedDate: "2023-02-15T10:25:00Z", - ModifiedDate: "2024-11-10T14:15:00Z", - }, - { - EntryId: 2003, - Id: 2003, - Name: "Michael Chen", - FullName: "Michael Chen", - Email: "m.chen@globalventures.com", - Phone: "+44-20-5555-0103", - Company: 1003, - Title: "Managing Director", - ContactType: 121, - IsPrimary: true, - CreatedDate: "2023-03-20T11:05:00Z", - ModifiedDate: "2024-11-15T10:00:00Z", - }, - { - EntryId: 2004, - Id: 2004, - Name: "Emily Rodriguez", - FullName: "Emily Rodriguez", - Email: "emily.r@acme.com", - Phone: "+1-555-0104", - Company: 1001, - Title: "CFO", - ContactType: 122, - IsPrimary: false, - CreatedDate: "2023-04-05T09:30:00Z", - ModifiedDate: "2024-09-20T16:45:00Z", - }, - ], - // Deal entries (entryTypeId: 3) - 3: [ - { - EntryId: 3001, - Id: 3001, - Name: "Series A - TechStart", - DealName: "Series A - TechStart", - DealAmount: 10000000.00, - DealStage: 131, // Entry list item for stage - TargetCompany: 1002, - CloseDate: "2024-12-31T00:00:00Z", - DealCurrency: "USD", - DealTeam: [ - 5001, - 5002, - ], - Probability: 75, - CreatedDate: "2024-06-01T10:00:00Z", - ModifiedDate: "2024-11-20T15:30:00Z", - }, - { - EntryId: 3002, - Id: 3002, - Name: "Acquisition - Acme Corp", - DealName: "Acquisition - Acme Corp", - DealAmount: 75000000.00, - DealStage: 132, - TargetCompany: 1001, - CloseDate: "2025-03-15T00:00:00Z", - DealCurrency: "USD", - DealTeam: [ - 5001, - 5003, - ], - Probability: 60, - CreatedDate: "2024-08-10T14:20:00Z", - ModifiedDate: "2024-11-23T11:15:00Z", - }, - { - EntryId: 3003, - Id: 3003, - Name: "Growth Investment - Global Ventures", - DealName: "Growth Investment - Global Ventures", - DealAmount: 25000000.00, - DealStage: 133, - TargetCompany: 1003, - CloseDate: "2024-11-30T00:00:00Z", - DealCurrency: "EUR", - DealTeam: [ - 5002, - ], - Probability: 90, - CreatedDate: "2024-05-15T09:45:00Z", - ModifiedDate: "2024-11-24T08:00:00Z", - }, - ], - // Fund entries (entryTypeId: 4) - 4: [ - { - EntryId: 4001, - Id: 4001, - Name: "Growth Fund I", - FundName: "Growth Fund I", - FundSize: 500000000.00, - FundCurrency: "USD", - VintageYear: 2020, - FundStatus: 141, - FundManager: 5001, - CreatedDate: "2020-01-15T10:00:00Z", - ModifiedDate: "2024-10-01T14:30:00Z", - }, - { - EntryId: 4002, - Id: 4002, - Name: "Venture Fund II", - FundName: "Venture Fund II", - FundSize: 750000000.00, - FundCurrency: "USD", - VintageYear: 2022, - FundStatus: 141, - FundManager: 5002, - CreatedDate: "2022-03-01T09:00:00Z", - ModifiedDate: "2024-11-15T11:20:00Z", - }, - { - EntryId: 4003, - Id: 4003, - Name: "European Opportunities Fund", - FundName: "European Opportunities Fund", - FundSize: 300000000.00, - FundCurrency: "EUR", - VintageYear: 2023, - FundStatus: 142, - FundManager: 5003, - CreatedDate: "2023-06-01T08:30:00Z", - ModifiedDate: "2024-11-20T10:00:00Z", - }, - ], - // Portfolio Company entries (entryTypeId: 5) - 5: [ - { - EntryId: 5001, - Id: 5001, - Name: "TechStart Inc", - PortfolioCompanyName: "TechStart Inc", - InvestmentAmount: 8000000.00, - InvestmentDate: "2023-09-15T00:00:00Z", - OwnershipPercentage: 15.5, - RelatedFund: 4001, - BoardRepresentation: true, - CreatedDate: "2023-09-15T14:00:00Z", - ModifiedDate: "2024-11-18T09:30:00Z", - }, - { - EntryId: 5002, - Id: 5002, - Name: "DataFlow Systems", - PortfolioCompanyName: "DataFlow Systems", - InvestmentAmount: 12000000.00, - InvestmentDate: "2022-11-20T00:00:00Z", - OwnershipPercentage: 22.3, - RelatedFund: 4002, - BoardRepresentation: true, - CreatedDate: "2022-11-20T10:15:00Z", - ModifiedDate: "2024-11-10T15:45:00Z", - }, - { - EntryId: 5003, - Id: 5003, - Name: "CloudScale Ltd", - PortfolioCompanyName: "CloudScale Ltd", - InvestmentAmount: 5000000.00, - InvestmentDate: "2024-02-10T00:00:00Z", - OwnershipPercentage: 10.0, - RelatedFund: 4003, - BoardRepresentation: false, - CreatedDate: "2024-02-10T11:30:00Z", - ModifiedDate: "2024-11-22T14:20:00Z", - }, - ], - // Entry list items (for dropdown/choice fields) - // Industry options (entryListId: 10) - 10: [ - { - EntryId: 101, - Id: 101, - Name: "Technology", - }, - { - EntryId: 102, - Id: 102, - Name: "Healthcare", - }, - { - EntryId: 103, - Id: 103, - Name: "Financial Services", - }, - { - EntryId: 104, - Id: 104, - Name: "Manufacturing", - }, - { - EntryId: 105, - Id: 105, - Name: "Retail", - }, - ], - // Tags options (entryListId: 11) - 11: [ - { - EntryId: 111, - Id: 111, - Name: "High Priority", - }, - { - EntryId: 112, - Id: 112, - Name: "Strategic", - }, - { - EntryId: 113, - Id: 113, - Name: "International", - }, - { - EntryId: 114, - Id: 114, - Name: "Early Stage", - }, - ], - // Contact Type options (entryListId: 12) - 12: [ - { - EntryId: 121, - Id: 121, - Name: "Executive", - }, - { - EntryId: 122, - Id: 122, - Name: "Finance", - }, - { - EntryId: 123, - Id: 123, - Name: "Operations", - }, - { - EntryId: 124, - Id: 124, - Name: "Legal", - }, - ], - // Deal Stage options (entryListId: 13) - 13: [ - { - EntryId: 131, - Id: 131, - Name: "Prospecting", - }, - { - EntryId: 132, - Id: 132, - Name: "Due Diligence", - }, - { - EntryId: 133, - Id: 133, - Name: "Negotiation", - }, - { - EntryId: 134, - Id: 134, - Name: "Closed Won", - }, - { - EntryId: 135, - Id: 135, - Name: "Closed Lost", - }, - ], - // Fund Status options (entryListId: 14) - 14: [ - { - EntryId: 141, - Id: 141, - Name: "Active", - }, - { - EntryId: 142, - Id: 142, - Name: "Fundraising", - }, - { - EntryId: 143, - Id: 143, - Name: "Closed", - }, - { - EntryId: 144, - Id: 144, - Name: "Liquidated", - }, - ], -}; - -/** - * Helper function to get mock data based on endpoint - * @param {string} endpoint - The API endpoint being called - * @param {object} params - Parameters for the endpoint (e.g., entryTypeId) - * @returns {any} The appropriate mock data - */ -export function getMockData(endpoint, params = {}) { - // GET /schema/entrytypes - if (endpoint === "/schema/entrytypes") { - return mockEntryTypes; - } - - // GET /schema/entrytypes/{entryTypeId}/fields - if (endpoint.match(/^\/schema\/entrytypes\/\d+\/fields$/)) { - const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[3]); - return mockEntryTypeFields[entryTypeId] || []; - } - - // GET data/entrydata/{entryTypeId}/entries - if (endpoint.match(/^data\/entrydata\/\d+\/entries$/)) { - const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[2]); - return mockEntries[entryTypeId] || []; - } - - // GET data/entrydata/rows/{entryTypeId} - Query entries with filtering support - if (endpoint.match(/^data\/entrydata\/rows\/\d+$/)) { - const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[3]); - let entries = mockEntries[entryTypeId] || []; - - // Handle query parameter for filtering by IDs - if (params.params?.query) { - const queryStr = params.params.query; - // Parse query like: {entryid: {$in:[1001,1002]}} - const idMatch = queryStr.match(/\$in:\[([^\]]+)\]/); - if (idMatch) { - const requestedIds = idMatch[1].split(",").map((id) => parseInt(id.trim())); - entries = entries.filter((entry) => { - const entryId = entry.EntryId || entry.Id || entry.id; - return requestedIds.includes(entryId); - }); - } - } - - return entries; - } - - // POST data/entrydata - Create entry - if (endpoint === "POST:data/entrydata") { - const { - entryTypeId, data, - } = params; - - // Validate that data is provided - if (!data || typeof data !== "object") { - return { - success: false, - error: "Invalid data provided for entry creation", - }; - } - - const entries = mockEntries[entryTypeId] || []; - // Generate a new ID based on existing entries - const maxId = entries.reduce((max, entry) => { - const id = entry.EntryId || entry.Id || entry.id || 0; - return Math.max(max, id); - }, 0); - const newId = maxId + 1; - - // Return a mock created entry with the new ID - const createdEntry = { - EntryId: newId, - Id: newId, - ...data, - CreatedDate: new Date().toISOString(), - ModifiedDate: new Date().toISOString(), - }; - - return { - success: true, - entry: createdEntry, - message: `Successfully created entry with ID ${newId}`, - }; - } - - // PUT data/entrydata - Update entry - if (endpoint === "PUT:data/entrydata") { - const { - entryTypeId, data, - } = params; - - // Validate that data is provided - if (!data || typeof data !== "object") { - return { - success: false, - error: "Invalid data provided for entry update", - }; - } - - // Extract entry ID from data - const entryId = data?.EntryId || data?.Id || data?.id; - - // Validate that an ID is provided - if (!entryId) { - return { - success: false, - error: "Entry ID is required for update operation", - }; - } - - // Check if entry exists in mock data - const entries = mockEntries[entryTypeId] || []; - const existingEntry = entries.find((entry) => { - const id = entry.EntryId || entry.Id || entry.id; - return id === entryId; - }); - - // Return a mock updated entry - const updatedEntry = { - EntryId: entryId, - Id: entryId, - ...data, - ModifiedDate: new Date().toISOString(), - }; - - return { - success: true, - entry: updatedEntry, - message: `Successfully updated entry with ID ${entryId}`, - existed: !!existingEntry, - }; - } - - // DELETE data/entrydata - Delete entry - if (endpoint === "DELETE:data/entrydata") { - const { data } = params; - - // Handle both single ID and array of IDs - let entryIds; - if (Array.isArray(data)) { - entryIds = data; - } else if (typeof data === "object") { - const entryId = data?.EntryId || data?.Id || data?.id; - entryIds = entryId - ? [ - entryId, - ] - : []; - } else { - entryIds = [ - data, - ]; - } - - // Return a mock success response - const count = entryIds.length; - return { - success: true, - deletedIds: entryIds, - count, - message: `Successfully deleted ${count} entr${count === 1 - ? "y" - : "ies"}: ID${count === 1 - ? "" - : "s"} ${entryIds.join(", ")}`, - }; - } - - // Default: return empty array - return []; -} - diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index 9b30aa124cd7c..c8b94cdde4665 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -1,5 +1,4 @@ -// import { axios } from "@pipedream/platform"; -import { getMockData } from "./common/mock-data.mjs"; +import { axios } from "@pipedream/platform"; export default { type: "app", @@ -46,13 +45,6 @@ export default { }, }, methods: { - /** - * Set this to true to use mock data instead of making real API requests - * Useful for testing without API access - */ - _useMockData() { - return true; - }, async _makeRequest({ $ = this, headers, ...args }) { @@ -64,13 +56,9 @@ export default { }, ...args, }; - $;return config; // while testing, return the config instead of making the request - // return axios($, config); + return axios($, config); }, async listEntryTypes(args = {}) { - if (this._useMockData()) { - return getMockData("/schema/entrytypes"); - } return this._makeRequest({ url: "/schema/entrytypes", ...args, @@ -79,11 +67,6 @@ export default { async getEntryTypeFields({ entryTypeId, ...args }) { - if (this._useMockData()) { - return getMockData(`/schema/entrytypes/${entryTypeId}/fields`, { - entryTypeId, - }); - } return this._makeRequest({ url: `/schema/entrytypes/${entryTypeId}/fields`, ...args, @@ -92,11 +75,6 @@ export default { async getAllEntryTypeEntries({ entryTypeId, ...args }) { - if (this._useMockData()) { - return getMockData(`data/entrydata/${entryTypeId}/entries`, { - entryTypeId, - }); - } return this._makeRequest({ url: `data/entrydata/${entryTypeId}/entries`, ...args, @@ -105,12 +83,6 @@ export default { async queryEntries({ entryTypeId, ...args }) { - if (this._useMockData()) { - return getMockData(`data/entrydata/rows/${entryTypeId}`, { - entryTypeId, - params: args.params, - }); - } return this._makeRequest({ url: `data/entrydata/rows/${entryTypeId}`, ...args, From fbbf4d30913688a6dd7c4f9bb109b5f0352aef76 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 23:13:52 -0300 Subject: [PATCH 14/16] Adjusting component versions --- components/dealcloud/actions/create-record/create-record.mjs | 2 +- components/dealcloud/actions/delete-records/delete-records.mjs | 2 +- components/dealcloud/actions/get-records/get-records.mjs | 2 +- components/dealcloud/actions/update-record/update-record.mjs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/dealcloud/actions/create-record/create-record.mjs b/components/dealcloud/actions/create-record/create-record.mjs index e1a6289c8d327..2cd90020eea99 100644 --- a/components/dealcloud/actions/create-record/create-record.mjs +++ b/components/dealcloud/actions/create-record/create-record.mjs @@ -5,7 +5,7 @@ export default { key: "dealcloud-create-record", name: "Create Record", description: "Creates a new record (entry) in DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/cells/postput)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", annotations: { destructiveHint: false, diff --git a/components/dealcloud/actions/delete-records/delete-records.mjs b/components/dealcloud/actions/delete-records/delete-records.mjs index f8bd5d6185fbd..3c3c7fa1c4486 100644 --- a/components/dealcloud/actions/delete-records/delete-records.mjs +++ b/components/dealcloud/actions/delete-records/delete-records.mjs @@ -5,7 +5,7 @@ export default { key: "dealcloud-delete-records", name: "Delete Record(s)", description: "Deletes one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/delete)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", annotations: { destructiveHint: true, diff --git a/components/dealcloud/actions/get-records/get-records.mjs b/components/dealcloud/actions/get-records/get-records.mjs index fc31f3e6de3e9..ada81428ce73c 100644 --- a/components/dealcloud/actions/get-records/get-records.mjs +++ b/components/dealcloud/actions/get-records/get-records.mjs @@ -5,7 +5,7 @@ export default { key: "dealcloud-get-records", name: "Get Record(s)", description: "Retrieves one or more records (entries) from DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/rows/get)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", annotations: { destructiveHint: false, diff --git a/components/dealcloud/actions/update-record/update-record.mjs b/components/dealcloud/actions/update-record/update-record.mjs index c32d98d988ad5..d9cc54241149c 100644 --- a/components/dealcloud/actions/update-record/update-record.mjs +++ b/components/dealcloud/actions/update-record/update-record.mjs @@ -11,7 +11,7 @@ export default { key: "dealcloud-update-record", name: "Update Record", description: "Updates a record (entry) in DealCloud. [See the documentation](https://api.docs.dealcloud.com/docs/data/cells/postput)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", annotations: { destructiveHint: false, From 60e267c80ce305e92410e146224cd329f8d48f0f Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 23:33:29 -0300 Subject: [PATCH 15/16] minor fixes --- .../actions/common/common-create-update.mjs | 2 +- .../actions/delete-records/delete-records.mjs | 2 +- components/dealcloud/common/mock-data.mjs | 4 ++-- components/dealcloud/common/utils.mjs | 3 ++- components/dealcloud/dealcloud.app.mjs | 16 ++++++++-------- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/components/dealcloud/actions/common/common-create-update.mjs b/components/dealcloud/actions/common/common-create-update.mjs index 438f86adbd55f..b37eb1c12ebde 100644 --- a/components/dealcloud/actions/common/common-create-update.mjs +++ b/components/dealcloud/actions/common/common-create-update.mjs @@ -16,7 +16,7 @@ export default { key, value, ]) => { - const fieldId = key.split("_")[1]; + const fieldId = Number(key.split("_")[1]); return { entryId: this.getEntryId(), fieldId, diff --git a/components/dealcloud/actions/delete-records/delete-records.mjs b/components/dealcloud/actions/delete-records/delete-records.mjs index f8bd5d6185fbd..bfd1f51333694 100644 --- a/components/dealcloud/actions/delete-records/delete-records.mjs +++ b/components/dealcloud/actions/delete-records/delete-records.mjs @@ -34,7 +34,7 @@ export default { }, }, async run({ $ }) { - const entryIds = checkIdArray(this.entryIds); + const entryIds = checkIdArray(this.entryIds).map(Number); const response = await this.app.deleteEntry({ $, entryTypeId: this.entryTypeId, diff --git a/components/dealcloud/common/mock-data.mjs b/components/dealcloud/common/mock-data.mjs index 488d0d2f61548..68b7181030257 100644 --- a/components/dealcloud/common/mock-data.mjs +++ b/components/dealcloud/common/mock-data.mjs @@ -1101,13 +1101,13 @@ export function getMockData(endpoint, params = {}) { } // GET data/entrydata/{entryTypeId}/entries - if (endpoint.match(/^data\/entrydata\/\d+\/entries$/)) { + if (endpoint.match(/^\/data\/entrydata\/\d+\/entries$/)) { const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[2]); return mockEntries[entryTypeId] || []; } // GET data/entrydata/rows/{entryTypeId} - Query entries with filtering support - if (endpoint.match(/^data\/entrydata\/rows\/\d+$/)) { + if (endpoint.match(/^\/data\/entrydata\/rows\/\d+$/)) { const entryTypeId = params.entryTypeId || parseInt(endpoint.split("/")[3]); let entries = mockEntries[entryTypeId] || []; diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs index 42a9ea32be8fa..86a9c72b2448b 100644 --- a/components/dealcloud/common/utils.mjs +++ b/components/dealcloud/common/utils.mjs @@ -3,7 +3,8 @@ import { CURRENCY_OPTIONS } from "./constants.mjs"; export function checkIdArray(value) { if (typeof value === "string") { - return value.split(","); + return value.split(",").map((id) => id.trim()) + .filter(Boolean); } if (Array.isArray(value)) { return value; diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index 9b30aa124cd7c..3916fe64985a0 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -57,7 +57,7 @@ export default { $ = this, headers, ...args }) { const config = { - baseURL: `${this.$auth.host}/api/rest/v4/`, + baseURL: `${this.$auth.host}/api/rest/v4`, headers: { ...headers, Authorization: `Bearer ${this.$auth.oauth_access_token}`, @@ -93,12 +93,12 @@ export default { entryTypeId, ...args }) { if (this._useMockData()) { - return getMockData(`data/entrydata/${entryTypeId}/entries`, { + return getMockData(`/data/entrydata/${entryTypeId}/entries`, { entryTypeId, }); } return this._makeRequest({ - url: `data/entrydata/${entryTypeId}/entries`, + url: `/data/entrydata/${entryTypeId}/entries`, ...args, }); }, @@ -106,13 +106,13 @@ export default { entryTypeId, ...args }) { if (this._useMockData()) { - return getMockData(`data/entrydata/rows/${entryTypeId}`, { + return getMockData(`/data/entrydata/rows/${entryTypeId}`, { entryTypeId, params: args.params, }); } return this._makeRequest({ - url: `data/entrydata/rows/${entryTypeId}`, + url: `/data/entrydata/rows/${entryTypeId}`, ...args, }); }, @@ -120,7 +120,7 @@ export default { entryTypeId, ...args }) { return this._makeRequest({ - url: `data/entrydata/${entryTypeId}`, + url: `/data/entrydata/${entryTypeId}`, method: "POST", ...args, }); @@ -129,7 +129,7 @@ export default { entryTypeId, ...args }) { return this._makeRequest({ - url: `data/entrydata/${entryTypeId}`, + url: `/data/entrydata/${entryTypeId}`, method: "PUT", ...args, }); @@ -138,7 +138,7 @@ export default { entryTypeId, ...args }) { return this._makeRequest({ - url: `data/entrydata/${entryTypeId}`, + url: `/data/entrydata/${entryTypeId}`, method: "DELETE", ...args, }); From 6f7c73feb83b40a95c519fccd99ae62ed0361b01 Mon Sep 17 00:00:00 2001 From: GTFalcao Date: Tue, 25 Nov 2025 23:38:08 -0300 Subject: [PATCH 16/16] Minor adjustments --- .../actions/delete-records/delete-records.mjs | 2 +- .../dealcloud/actions/get-records/get-records.mjs | 2 +- components/dealcloud/common/utils.mjs | 14 +------------- components/dealcloud/dealcloud.app.mjs | 3 ++- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/components/dealcloud/actions/delete-records/delete-records.mjs b/components/dealcloud/actions/delete-records/delete-records.mjs index e238621c8f24e..a8c73568e07d4 100644 --- a/components/dealcloud/actions/delete-records/delete-records.mjs +++ b/components/dealcloud/actions/delete-records/delete-records.mjs @@ -41,7 +41,7 @@ export default { data: entryIds, }); - const count = entryIds.length; + const count = response.length; $.export("$summary", `Successfully deleted ${count} record${count === 1 ? "" : "s"}`); diff --git a/components/dealcloud/actions/get-records/get-records.mjs b/components/dealcloud/actions/get-records/get-records.mjs index ada81428ce73c..4a9013e871f87 100644 --- a/components/dealcloud/actions/get-records/get-records.mjs +++ b/components/dealcloud/actions/get-records/get-records.mjs @@ -45,7 +45,7 @@ export default { }, }); - const count = entryIds.length; + const count = response.length; $.export("$summary", `Successfully retrieved ${count} record${count === 1 ? "" : "s"}`); diff --git a/components/dealcloud/common/utils.mjs b/components/dealcloud/common/utils.mjs index 86a9c72b2448b..763e1e9bc443f 100644 --- a/components/dealcloud/common/utils.mjs +++ b/components/dealcloud/common/utils.mjs @@ -87,20 +87,8 @@ export function convertFieldsToProps(fields) { } if (field.entryLists?.length) { + // TODO: add dynamic options for entry lists prop.description = prop.description + ` Entry List ID: \`${field.entryLists[0]}\``; - // prop.options = async () => { - // const results = await this.dealcloud.getAllEntryTypeEntries({ - // entryTypeId: field.entryLists[0], - // }); - // return results.map((entry) => { - // const value = entry.EntryId || entry.Id || entry.id; - // const label = entry.Name || value; - // return { - // label, - // value, - // }; - // }); - // }; } acc[`field_${field.id}`] = prop; diff --git a/components/dealcloud/dealcloud.app.mjs b/components/dealcloud/dealcloud.app.mjs index ebaf65dbdeed3..3d02b0fbfa977 100644 --- a/components/dealcloud/dealcloud.app.mjs +++ b/components/dealcloud/dealcloud.app.mjs @@ -83,10 +83,11 @@ export default { async queryEntries({ entryTypeId, ...args }) { - return this._makeRequest({ + const response = await this._makeRequest({ url: `/data/entrydata/rows/${entryTypeId}`, ...args, }); + return response?.rows || []; }, async createEntry({ entryTypeId, ...args