From bfc12b22292a0b07b41911ed4cf58fefbb6c51ff Mon Sep 17 00:00:00 2001 From: Vincent FINET Date: Fri, 9 Aug 2024 16:48:37 +0200 Subject: [PATCH] fix small issues on Beryllium about custom object share and friends to be ignore, and reduce the maxRequest used in JSForce to 15. --- .forceignore | 5 ++- .../core/orgcheck-api-sfconnectionmanager.js | 36 ++++++++++++++----- .../dataset/orgcheck-api-dataset-object.js | 4 +-- .../dataset/orgcheck-api-dataset-objects.js | 35 ++++++++---------- sfdx-project.json | 4 +-- 5 files changed, 50 insertions(+), 34 deletions(-) diff --git a/.forceignore b/.forceignore index 7b5b5a71..3d36001b 100755 --- a/.forceignore +++ b/.forceignore @@ -9,4 +9,7 @@ package.xml **/.eslintrc.json # LWC Jest -**/__tests__/** \ No newline at end of file +**/__tests__/** +**/tsconfig.json + +**/*.ts diff --git a/force-app/main/default/lwc/orgcheckApp/api/core/orgcheck-api-sfconnectionmanager.js b/force-app/main/default/lwc/orgcheckApp/api/core/orgcheck-api-sfconnectionmanager.js index ea55572e..af766cc5 100644 --- a/force-app/main/default/lwc/orgcheckApp/api/core/orgcheck-api-sfconnectionmanager.js +++ b/force-app/main/default/lwc/orgcheckApp/api/core/orgcheck-api-sfconnectionmanager.js @@ -64,7 +64,7 @@ export class OrgCheckSalesforceManager { this.#connection = new jsConnectionFactory.Connection({ accessToken: accessToken, version: SF_API_VERSION + '.0', - maxRequest: '20' // default is 10, we set it to 20 + maxRequest: 15 // making sure we set it to a reasonable value = 15 }); this.#lastRequestToSalesforce = undefined; this.#lastApiUsage = 0; @@ -275,6 +275,13 @@ export class OrgCheckSalesforceManager { let nbQueriesDone = 0, nbQueriesByPassed = 0, nbQueriesError = 0, nbQueryMore = 0, nbQueriesPending = queries.length; return Promise.all(queries.map((query) => { const conn = query.tooling === true ? this.#connection.tooling : this.#connection; + const sequential_query = (callback) => { + if (query.queryMore === false) { + conn.query(`${query.string} LIMIT 2000 OFFSET ${nbQueryMore * 2000}`, { autoFetch: false }, callback); + } else { + conn.query(query.string, { autoFetch: true }, callback); + } + } return new Promise((resolve, reject) => { const records = []; const recursive_query = (e, d) => { @@ -291,18 +298,31 @@ export class OrgCheckSalesforceManager { nbQueriesPending--; } else { records.push(... d.records); - if (d.done === true || (d.done === false && query.queryMore === false)) { - nbQueriesDone++; - nbQueriesPending--; - resolve({ records: records }); + if (query.queryMore === false) { + // Here we can't call queryMore (the sobject in the FROM statment does not support it, like EntityDefinition) + if (d.records.length < 2000) { + nbQueriesDone++; + nbQueriesPending--; + resolve({ records: records }); + } else { + nbQueryMore++; + sequential_query(recursive_query); + } } else { - nbQueryMore++; - conn.queryMore(d.nextRecordsUrl, recursive_query); + // Here we can call queryMore if fetching is not done... + if (d.done === true) { + nbQueriesDone++; + nbQueriesPending--; + resolve({ records: records }); + } else { + nbQueryMore++; + conn.queryMore(d.nextRecordsUrl, recursive_query); + } } } localLogger?.log(`Statistics of ${queries.length} SOQL ${queries.length>1?'queries':'query'}: ${nbQueryMore} queryMore done, ${nbQueriesPending} pending, ${nbQueriesDone} done, ${nbQueriesByPassed} by-passed, ${nbQueriesError} in error...`); } - conn.query(query.string, { autoFetch: query.queryMore === true ? true : false }, recursive_query); + sequential_query(recursive_query); }); })); } diff --git a/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-object.js b/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-object.js index 9bfffa81..142c3ae0 100644 --- a/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-object.js +++ b/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-object.js @@ -32,7 +32,6 @@ export class OrgCheckDatasetObject extends OrgCheckDataset { const results = await Promise.all([ sfdcManager.describe(fullObjectApiName), sfdcManager.soqlQuery([{ - queryMore: false, // we should have only one record max so no need to have queryMore activated. tooling: true, // We need the tooling to get the Description, ApexTriggers, FieldSets, ... which are not accessible from REST API) string: 'SELECT Id, DurableId, DeveloperName, Description, NamespacePrefix, ExternalSharingModel, InternalSharingModel, '+ '(SELECT DurableId, QualifiedApiName, Description, IsIndexed FROM Fields), '+ @@ -45,7 +44,8 @@ export class OrgCheckDatasetObject extends OrgCheckDataset { '(SELECT Id, Name FROM WebLinks) '+ 'FROM EntityDefinition '+ `WHERE QualifiedApiName = '${fullObjectApiName}' `+ - (!packageName ? `AND PublisherId IN ('System', '')` : `AND NamespacePrefix = '${packageName}' `) + (packageName ? `AND NamespacePrefix = '${packageName}' `: '') + + 'LIMIT 1' // We should get zero or one record, not more! }]), sfdcManager.recordCount(fullObjectApiName) ]); diff --git a/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-objects.js b/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-objects.js index c7e89d04..981af0a6 100644 --- a/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-objects.js +++ b/force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-objects.js @@ -9,39 +9,32 @@ export class OrgCheckDatasetObjects extends OrgCheckDataset { // Init the factory and records const objectDataFactory = dataFactory.getInstance(SFDC_Object); - // First SOQL query - localLogger.log(`Querying REST API about Organization in the org...`); - const results = await sfdcManager.soqlQuery([{ - string: 'SELECT NamespacePrefix FROM Organization' - }], localLogger); - - // Get the namespace of the org (if any) - const localNamespace = results[0].records[0].NamespacePrefix; - // Two actions to perform in parallel, global describe and an additional entity definition soql query localLogger.log(`Performing a global describe and in parallel a SOQL query to EntityDefinition...`); - const resultss = await Promise.all([ + const results = await Promise.all([ // Requesting information from the current salesforce org sfdcManager.describeGlobal(), // not using tooling api !!! // Some information are not in the global describe, we need to append them with EntityDefinition soql query sfdcManager.soqlQuery([{ - queryMore: false, // entityDef does not support calling QueryMore - tooling: false, // so not using tooling either!!! + queryMore: false, // entityDef does not support calling QueryMore, we will get records with LIMIT/OFFSET string: 'SELECT DurableId, NamespacePrefix, DeveloperName, QualifiedApiName, '+ 'ExternalSharingModel, InternalSharingModel '+ - 'FROM EntityDefinition ' + - `WHERE PublisherId IN ('System', '', '${localNamespace}') ` + - 'AND keyPrefix <> null '+ - 'AND DeveloperName <> null '+ - `AND (NOT(keyPrefix IN ('00a', '017', '0D5', '02c', '01j', '0jE','0Jf','0Ob','00I','0aA'))) `+ // filtering the feed, share, history, ... - 'LIMIT 2000 ' // Just to make sure we are not throwing EXCEEDED_ID_LIMIT and still got the first 2000 rows - }]) + 'FROM EntityDefinition '+ + 'WHERE keyPrefix <> null '+ + 'AND DeveloperName <> null '+ + `AND (NOT(keyPrefix IN ('00a', '017', '02c', '0D5', '1CE'))) ` + // 00a *Comment for custom objects + // 017 *History for custom objects + // 02c *Share for custom objects + // 0D5 *Feed for custom objects + // 1CE *Event for custom objects + }]) ]) - const objectsDescription = resultss[0]; - const entities = resultss[1][0].records; + const objectsDescription = results[0]; + const entities = results[1][0].records; const entitiesByName = {}; const qualifiedApiNames = await OrgCheckProcessor.carte( entities, diff --git a/sfdx-project.json b/sfdx-project.json index 02252b37..3a8328f7 100755 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -5,7 +5,7 @@ "default": true, "package": "OrgCheck", "versionName": "Beryllium", - "versionNumber": "4.4.0.NEXT", + "versionNumber": "4.5.0.NEXT", "versionDescription": "Org Check is an easy-to-install and easy-to-use Salesforce application in order to quickly analyze your org and its technical debt." } ], @@ -18,6 +18,6 @@ "OrgCheck@1.9.7-2": "04t7R000001IG9JQAW", "OrgCheck@2.4.2-1": "04t7R0000018kAuQAI", "OrgCheck@2.5.2-1": "04t7R000001hrl1QAA", - "OrgCheck@4.4.0-1": "04t7R000001uGWuQAM" + "OrgCheck@4.5.0-1": "04t7R000001uGX4QAM" } } \ No newline at end of file