chore: Upgrade jsforce to 3.6.2 and use jsforce-node (#18363)

* Upgrade jsforce to 3.6.2

* Refactor connecting to Salesforce

* Revert yarn.lock changes

* Migrate callback endpoint

* Add jsforce node dependency

* Migrate add endpoint

* Import

* Import package into crmService

* Use new package types

* Type fix

* Update vite config

* Push updated lockfile

* Attempt to bump platform/libraries to unlock jsforce

* Also update lockfile, naturally

* bump platform libraries

* Update vite.config

* Add jsforce to vite config

* fixup! Merge branch 'main' into upgrade-jsforce-v3

* fixup! fixup! Merge branch 'main' into upgrade-jsforce-v3

---------

Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Morgan Vernay <morgan@cal.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
This commit is contained in:
Joe Au-Yeung
2025-01-09 20:24:06 +00:00
committed by GitHub
co-authored by Alex van Andel Morgan Morgan Vernay Omar López Anik Dhabal Babu
parent 4902c6a0f8
commit 2a29155641
8 changed files with 7503 additions and 450 deletions
+1
View File
@@ -59,6 +59,7 @@
"googleapis": "^84.0.0",
"helmet": "^7.1.0",
"ioredis": "^5.3.2",
"jsforce": "^1.11.0",
"luxon": "^3.4.4",
"nest-winston": "^1.9.4",
"next-auth": "^4.22.1",
+9 -19
View File
@@ -68,14 +68,11 @@
]
},
{
"group": "Calendars",
"icon": "<i class='fa-light fa-calendar' style='color: #cfd2d8;'></i>",
"iconType": "custom",
"pages": [
"calendars/how-to-add-google-calendar",
"calendars/how-to-add-apple-calendar"
]
},
"group": "Calendars",
"icon": "<i class='fa-light fa-calendar' style='color: #cfd2d8;'></i>",
"iconType": "custom",
"pages": ["calendars/how-to-add-google-calendar", "calendars/how-to-add-apple-calendar"]
},
{
"group": "Event Types",
"icon": "calendar",
@@ -135,11 +132,7 @@
"group": "Bookings",
"icon": "calendar-check",
"iconType": "solid",
"pages": [
"bookings/no-show",
"bookings/paid-bookings",
"bookings/prefill-fields"
]
"pages": ["bookings/no-show", "bookings/paid-bookings", "bookings/prefill-fields"]
},
{
"group": "Embedding",
@@ -158,10 +151,7 @@
"group": "Auth and Provisioning",
"icon": "user-lock",
"iconType": "solid",
"pages": [
"auth-and-provision/scim-okta",
"auth-and-provision/oidc-with-okta"
]
"pages": ["auth-and-provision/scim-okta", "auth-and-provision/oidc-with-okta"]
},
{
"group": "Apps and Integrations",
@@ -176,7 +166,7 @@
"apps-and-integrations/how-to-build-an-app",
"apps-and-integrations/syncing-third-party"
]
},
}
]
}
],
@@ -185,4 +175,4 @@
"linkedin": "https://www.linkedin.com/company/cal-com/",
"discord": "https://discord.com/invite/calcom"
}
}
}
+8 -4
View File
@@ -1,4 +1,4 @@
import jsforce from "jsforce";
import jsforce from "@jsforce/jsforce-node";
import type { NextApiRequest, NextApiResponse } from "next";
import { WEBAPP_URL_FOR_OAUTH } from "@calcom/lib/constants";
@@ -16,13 +16,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if (!consumer_key) return res.status(400).json({ message: "Salesforce client id missing." });
const salesforceClient = new jsforce.Connection({
clientId: consumer_key,
redirectUri: `${WEBAPP_URL_FOR_OAUTH}/api/integrations/salesforce/callback`,
oauth2: {
clientId: consumer_key,
redirectUri: `${WEBAPP_URL_FOR_OAUTH}/api/integrations/salesforce/callback`,
},
});
const state = encodeOAuthState(req);
const url = salesforceClient.oauth2.getAuthorizationUrl({
scope: "refresh_token full",
state: encodeOAuthState(req),
...(state && { state }),
});
res.status(200).json({ url });
}
@@ -1,4 +1,4 @@
import jsforce from "jsforce";
import jsforce from "@jsforce/jsforce-node";
import type { NextApiRequest, NextApiResponse } from "next";
import { WEBAPP_URL_FOR_OAUTH } from "@calcom/lib/constants";
@@ -33,9 +33,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if (!consumer_secret) return res.status(400).json({ message: "Salesforce consumer secret missing." });
const conn = new jsforce.Connection({
clientId: consumer_key,
clientSecret: consumer_secret,
redirectUri: `${WEBAPP_URL_FOR_OAUTH}/api/integrations/salesforce/callback`,
oauth2: {
clientId: consumer_key,
clientSecret: consumer_secret,
redirectUri: `${WEBAPP_URL_FOR_OAUTH}/api/integrations/salesforce/callback`,
},
});
const salesforceTokenInfo = await conn.oauth2.requestToken(code as string);
@@ -1,5 +1,5 @@
import type { TokenResponse } from "jsforce";
import jsforce from "jsforce";
import type { TokenResponse, Connection, Field } from "@jsforce/jsforce-node";
import jsforce from "@jsforce/jsforce-node";
import { RRule } from "rrule";
import { z } from "zod";
@@ -64,7 +64,7 @@ const salesforceTokenSchema = z.object({
export default class SalesforceCRMService implements CRM {
private integrationName = "";
private conn!: Promise<jsforce.Connection>;
private conn!: Promise<Connection>;
private log: typeof logger;
private calWarnings: string[] = [];
private appOptions: any;
@@ -87,6 +87,10 @@ export default class SalesforceCRMService implements CRM {
private getClient = async (credential: CredentialPayload) => {
const { consumer_key, consumer_secret } = await getSalesforceAppKeys();
const credentialKey = credential.key as unknown as ExtendedTokenResponse;
if (!credentialKey.refresh_token)
throw new Error(`Refresh token is missing for credential ${credential.id}`);
try {
/* XXX: This code results in 'Bad Request', which indicates something is wrong with our salesforce integration.
Needs further investigation ASAP */
@@ -121,9 +125,11 @@ export default class SalesforceCRMService implements CRM {
}
return new jsforce.Connection({
clientId: consumer_key,
clientSecret: consumer_secret,
redirectUri: `${WEBAPP_URL}/api/integrations/salesforce/callback`,
oauth2: {
clientId: consumer_key,
clientSecret: consumer_secret,
redirectUri: `${WEBAPP_URL}/api/integrations/salesforce/callback`,
},
instanceUrl: credentialKey.instance_url,
accessToken: credentialKey.access_token,
refreshToken: credentialKey.refresh_token,
@@ -768,7 +774,7 @@ export default class SalesforceCRMService implements CRM {
const conn = await this.conn;
const fieldSet = new Set(fieldsToTest);
const foundFields: jsforce.Field[] = [];
const foundFields: Field[] = [];
try {
const salesforceEntity = await conn.describe(sobject);
@@ -953,7 +959,7 @@ export default class SalesforceCRMService implements CRM {
organizerEmail,
calEventResponses,
}: {
existingFields: jsforce.Field[];
existingFields: Field[];
personRecord: Record<string, any>;
onBookingWriteToRecordFields: Record<string, any>;
startTime: string;
@@ -1113,7 +1119,7 @@ export default class SalesforceCRMService implements CRM {
private async fetchPersonRecord(
contactId: string,
existingFields: jsforce.Field[],
existingFields: Field[],
personRecordType: SalesforceRecordEnum
): Promise<Record<string, any> | null> {
const conn = await this.conn;
+2 -3
View File
@@ -7,10 +7,9 @@
"dependencies": {
"@calcom/lib": "*",
"@calcom/prisma": "*",
"jsforce": "^1.11.0"
"@jsforce/jsforce-node": "^3.6.3"
},
"devDependencies": {
"@calcom/types": "*",
"@types/jsforce": "^1.11.0"
"@calcom/types": "*"
}
}
@@ -66,6 +66,7 @@ export default defineConfig({
"lru-cache",
"next-auth/jwt",
"memory-cache",
"@jsforce/jsforce-node",
"jsforce",
"axios",
"qs",
@@ -137,6 +138,7 @@ export default defineConfig({
"lru-cache": "lru-cache",
"next-auth/jwt": "next-auth/jwt",
"memory-cache": "memory-cache",
"@jsforce-node": "@jsforce/jsforce-node",
jsforce: "jsforce",
axios: "axios",
qs: "qs",
+7460 -411
View File
File diff suppressed because it is too large Load Diff