Skip to content

Commit 7e22812

Browse files
authored
Merge pull request #372 from SalesforceLabs/Beryllium-UAT
Beryllium uat
2 parents fdb3c3a + d9c095d commit 7e22812

File tree

10 files changed

+136
-292
lines changed

10 files changed

+136
-292
lines changed

force-app/main/default/lwc/orgcheckApp/api/core/orgcheck-api-sfconnectionmanager.js

Lines changed: 76 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,6 @@ export class OrgCheckSalesforceManager {
217217
}
218218
}
219219

220-
splitIdsInBatches(ids, batchsize, callback) {
221-
if (batchsize <= 0) return;
222-
for (let i = 0; i < ids.length; i += batchsize) {
223-
callback('\''+ids.slice(i, Math.min(i + batchsize, ids.length)).join('\',\'')+'\'');
224-
}
225-
}
226-
227220
getObjectType(apiName, isCustomSetting) {
228221
if (isCustomSetting === true) return OBJECTTYPE_ID_CUSTOM_SETTING;
229222
if (apiName.endsWith('__c')) return OBJECTTYPE_ID_CUSTOM_SOBJECT;
@@ -317,59 +310,52 @@ export class OrgCheckSalesforceManager {
317310
.then((results) => {
318311
// Getting the Ids for DAPI call
319312
const ids = results.records.map((record) => this.caseSafeId(record[q.addDependenciesBasedOnField]));
320-
// We are going to split the DAPI calls into batches for <n> ids at the same time
321-
const dapiPromises = [];
322-
this.splitIdsInBatches(ids, 50, (subids) => {
323-
dapiPromises.push(new Promise((resolve, reject) => {
324-
this.#connection.tooling.query(
325-
'SELECT MetadataComponentId, MetadataComponentName, MetadataComponentType, '+
326-
'RefMetadataComponentId, RefMetadataComponentName, RefMetadataComponentType '+
327-
'FROM MetadataComponentDependency '+
328-
`WHERE (RefMetadataComponentId IN (${subids}) OR MetadataComponentId IN (${subids}))`,
329-
(e, d) => {
330-
this._watchDog__afterRequest(reject);
331-
if (e) {
332-
e.context = {
333-
when: 'While getting the dependencies from DAPI',
334-
what: {
335-
allIds: ids,
336-
concernedIds: subids
337-
}
338-
};
339-
reject(e);
340-
} else {
341-
resolve(d.records.map((e) => { return {
342-
id: this.caseSafeId(e.MetadataComponentId),
343-
name: e.MetadataComponentName,
344-
type: e.MetadataComponentType,
345-
url: this.setupUrl(e.MetadataComponentType, e.MetadataComponentId),
346-
refId: this.caseSafeId(e.RefMetadataComponentId),
347-
refName: e.RefMetadataComponentName,
348-
refType: e.RefMetadataComponentType,
349-
refUrl: this.setupUrl(e.RefMetadataComponentType, e.RefMetadataComponentId),
350-
}}));
351-
}
313+
return this._callComposite(ids, true, '/query?q='+
314+
'SELECT MetadataComponentId, MetadataComponentName, MetadataComponentType, '+
315+
'RefMetadataComponentId, RefMetadataComponentName, RefMetadataComponentType '+
316+
'FROM MetadataComponentDependency '+
317+
'WHERE RefMetadataComponentId = \'(id)\' '+
318+
'OR MetadataComponentId = \'(id)\' ')
319+
.then(allDependenciesResults => {
320+
// We are going to append the dependencies in the results
321+
const allDependencies = [];
322+
// Using a set to filter duplicates
323+
const duplicateCheck = new Set();
324+
// We parse all the batches/results from the DAPI
325+
allDependenciesResults
326+
.filter(r => r.done === true && r.totalSize > 0)
327+
.forEach(r => allDependencies.push(... r.records.map((e) => {
328+
const id = this.caseSafeId(e.MetadataComponentId);
329+
const refId = this.caseSafeId(e.RefMetadataComponentId);
330+
const key = `${id}-${refId}`;
331+
if (duplicateCheck.has(key)) return null;
332+
duplicateCheck.add(key);
333+
return {
334+
id: id,
335+
name: e.MetadataComponentName,
336+
type: e.MetadataComponentType,
337+
url: this.setupUrl(e.MetadataComponentType, e.MetadataComponentId),
338+
refId: refId,
339+
refName: e.RefMetadataComponentName,
340+
refType: e.RefMetadataComponentType,
341+
refUrl: this.setupUrl(e.RefMetadataComponentType, e.RefMetadataComponentId),
352342
}
353-
);
354-
}));
343+
})));
344+
// Remove duplicates
345+
results.allDependencies = allDependencies.filter(r => r !== null);
346+
// Return the altered results
347+
return results;
348+
})
349+
.catch(error => {
350+
error.context = {
351+
when: 'While getting the dependencies from DAPI',
352+
what: {
353+
allIds: ids,
354+
concernedIds: subids
355+
}
356+
};
357+
return error;
355358
});
356-
return Promise.all(dapiPromises)
357-
.then((allDependenciesResults) => {
358-
// We are going to append the dependencies in the results
359-
results.allDependencies = [];
360-
// We parse all the batches/results from the DAPI
361-
allDependenciesResults.forEach((dependencies) => {
362-
if (dependencies) {
363-
// Merge them into one array
364-
results.allDependencies.push(... dependencies);
365-
}
366-
});
367-
// Return the altered results
368-
return results;
369-
})
370-
.catch((error) => {
371-
console.error('Issue while parsing results from DAPI', error);
372-
});
373359
})
374360
.catch((error) => {
375361
console.error('Issue while accessing DAPI', error);
@@ -446,42 +432,42 @@ export class OrgCheckSalesforceManager {
446432
});
447433
}
448434

449-
async readMetadataAtScale(type, ids, byPasses) {
435+
async _callComposite(ids, tooling, uriPattern, byPasses) {
450436
this._watchDog__beforeRequest();
451-
return new Promise((resolve, reject) => {
452-
const compositeRequestBodies = [];
453-
let currentCompositeRequestBody;
454-
const BATCH_MAX_SIZE = 25; // Composite can't handle more than 25 records per request
455-
ids.forEach((id) => {
456-
if (!currentCompositeRequestBody || currentCompositeRequestBody.compositeRequest.length === BATCH_MAX_SIZE) {
457-
currentCompositeRequestBody = {
458-
allOrNone: false,
459-
compositeRequest: []
460-
};
461-
compositeRequestBodies.push(currentCompositeRequestBody);
462-
}
463-
currentCompositeRequestBody.compositeRequest.push({
464-
url: `/services/data/v${this.#connection.version}/tooling/sobjects/${type}/${id}`,
465-
method: 'GET',
466-
referenceId: id
467-
});
437+
const BATCH_MAX_SIZE = 25; // Composite can't handle more than 25 records per request
438+
const compositeRequestBodies = [];
439+
let currentCompositeRequestBody;
440+
ids.forEach((id) => {
441+
if (!currentCompositeRequestBody || currentCompositeRequestBody.compositeRequest.length === BATCH_MAX_SIZE) {
442+
currentCompositeRequestBody = {
443+
allOrNone: false,
444+
compositeRequest: []
445+
};
446+
compositeRequestBodies.push(currentCompositeRequestBody);
447+
}
448+
currentCompositeRequestBody.compositeRequest.push({
449+
url: `/services/data/v${this.#connection.version}${tooling === true ? '/tooling' : ''}${uriPattern.replaceAll('(id)', id)}`,
450+
method: 'GET',
451+
referenceId: id
468452
});
469-
const promises = [];
470-
compositeRequestBodies.forEach((requestBody) => {
471-
promises.push(new Promise((r, e) => {
453+
});
454+
return new Promise((resolve, reject) => {
455+
Promise.all(
456+
compositeRequestBodies.map((requestBody) => new Promise((r, e) => {
472457
this.#connection.request({
473-
url: `/services/data/v${this.#connection.version}/tooling/composite`,
458+
url: `/services/data/v${this.#connection.version}${tooling === true ? '/tooling' : ''}/composite`,
474459
method: 'POST',
475460
body: JSON.stringify(requestBody),
476461
headers: { 'Content-Type': 'application/json' }
477462
}, (error, response) => {
478463
this._watchDog__afterRequest(e);
479464
if (error) {
480465
error.context = {
481-
when: 'While creating a promise to call the Tooling Composite API.',
466+
when: `While creating a promise to call the ${tooling === true ? 'Tooling Composite API' : 'Composite API'}.`,
482467
what: {
483-
type: metadataInformation.type,
484-
ids: metadataInformation.ids,
468+
tooling: tooling,
469+
pattern: uriPattern,
470+
ids: ids,
485471
body: requestBody
486472
}
487473
};
@@ -491,9 +477,7 @@ export class OrgCheckSalesforceManager {
491477
}
492478
}
493479
);
494-
}));
495-
});
496-
Promise.all(promises)
480+
})))
497481
.then((results) => {
498482
const records = [];
499483
results.forEach((result) => {
@@ -507,7 +491,8 @@ export class OrgCheckSalesforceManager {
507491
error.context = {
508492
when: 'After receiving a response with bad HTTP status code.',
509493
what: {
510-
type: type,
494+
tooling: tooling,
495+
pattern: uriPattern,
511496
ids: ids,
512497
body: response.body
513498
}
@@ -523,6 +508,10 @@ export class OrgCheckSalesforceManager {
523508
});
524509
}
525510

511+
async readMetadataAtScale(type, ids, byPasses) {
512+
return this._callComposite(ids, true, `/sobjects/${type}/(id)`, byPasses);
513+
}
514+
526515
/**
527516
* Method to get the list of sobjects
528517
*/

force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-apextriggers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { OrgCheckDataset } from '../core/orgcheck-api-dataset';
22
import { SFDC_ApexTrigger } from '../data/orgcheck-api-data-apextrigger';
33

44
const REGEX_HASSOQL = new RegExp("\\[\\s*(?:SELECT|FIND)");
5-
const REGEX_HASDML = new RegExp("(?:insert|update|delete)\\s*(?:\\w+|\\(|\\[)");
5+
const REGEX_HASDML = new RegExp("(?:insert|update|delete)\\s*(?:\\s\\w+|\\(|\\[)");
66

77
export class OrgCheckDatasetApexTriggers extends OrgCheckDataset {
88

force-app/main/default/lwc/orgcheckApp/api/dataset/orgcheck-api-dataset-packages.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export class OrgCheckDatasetPackages extends OrgCheckDataset {
3030

3131
// Set the map (2/2) - local package
3232
localLogger.log(`Parsing ${results[1].records.length} local packages...`);
33-
results[1].records.forEach((record) => {
33+
results[1].records.filter((record) => record.NamespacePrefix !== null).forEach((record) => {
3434
packages.set('<local>', new SFDC_Package({
3535
id: record.NamespacePrefix,
3636
name: record.NamespacePrefix,

0 commit comments

Comments
 (0)