@salesforce/source-tracking
Version:
API for tracking local and remote Salesforce metadata changes
89 lines • 4.43 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.queryFn = exports.querySourceMembersFrom = exports.querySourceMembersTo = exports.calculateTimeout = void 0;
/*
* Copyright 2025, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const core_1 = require("@salesforce/core");
const kit_1 = require("@salesforce/kit");
const types_1 = require("./types");
const calculateTimeout = (logger) => (memberCount) => {
const overriddenTimeout = core_1.envVars.getNumber('SF_SOURCE_MEMBER_POLLING_TIMEOUT', 0);
if (overriddenTimeout > 0) {
logger.debug(`Overriding SourceMember polling timeout to ${overriddenTimeout}`);
return kit_1.Duration.seconds(overriddenTimeout);
}
// Calculate a polling timeout for SourceMembers based on the number of
// member names being polled plus a buffer of 5 seconds. This will
// wait 50s for each 1000 components, plus 5s.
const pollingTimeout = Math.ceil(memberCount * 0.05) + 5;
logger.debug(`Computed SourceMember polling timeout of ${pollingTimeout}s`);
return kit_1.Duration.seconds(pollingTimeout);
};
exports.calculateTimeout = calculateTimeout;
/** exported only for spy/mock */
const querySourceMembersTo = async (conn, toRevision) => {
const query = `SELECT ${types_1.SOURCE_MEMBER_FIELDS.join(', ')} FROM SourceMember WHERE RevisionCounter <= ${toRevision}`;
return (0, exports.queryFn)(conn, query);
};
exports.querySourceMembersTo = querySourceMembersTo;
const querySourceMembersFrom = async ({ conn, fromRevision, queryCache, userQueryCache, logger, }) => {
if (queryCache) {
// Check cache first and return if found.
const cachedQueryResult = queryCache.get(fromRevision);
if (cachedQueryResult) {
logger?.debug(`Using cache for SourceMember query for revision ${fromRevision}`);
return cachedQueryResult;
}
}
// because `serverMaxRevisionCounter` is always updated, we need to select > to catch the most recent change
const query = `SELECT ${types_1.SOURCE_MEMBER_FIELDS.join(', ')} FROM SourceMember WHERE RevisionCounter > ${fromRevision}`;
logger?.debug(`Query: ${query}`);
const queryResult = await (0, exports.queryFn)(conn, query);
if (userQueryCache) {
await updateCacheWithUnknownUsers(conn, queryResult, userQueryCache);
}
const queryResultWithResolvedUsers = queryResult.map((member) => ({
...member,
ChangedBy: userQueryCache?.get(member.ChangedBy) ?? member.ChangedBy,
}));
queryCache?.set(fromRevision, queryResultWithResolvedUsers);
return queryResultWithResolvedUsers;
};
exports.querySourceMembersFrom = querySourceMembersFrom;
const queryFn = async (conn, query) => {
try {
return (await conn.tooling.query(query, { autoFetch: true, maxFetch: 50_000 })).records.map(sourceMemberCorrections);
}
catch (error) {
throw core_1.SfError.wrap(error);
}
};
exports.queryFn = queryFn;
/** A series of workarounds for server-side bugs. Each bug should be filed against a team, with a WI, so we know when these are fixed and can be removed */
const sourceMemberCorrections = (sourceMember) => {
if (sourceMember.MemberType === 'QuickActionDefinition') {
return { ...sourceMember, MemberType: 'QuickAction' }; // W-15837125
}
return sourceMember;
};
const updateCacheWithUnknownUsers = async (conn, queryResult, userCache) => {
const unknownUsers = new Set(queryResult.map((member) => member.ChangedBy).filter((u) => !userCache.has(u)));
if (unknownUsers.size > 0) {
const userQuery = `SELECT Id, Name FROM User WHERE Id IN ('${Array.from(unknownUsers).join("','")}')`;
(await conn.query(userQuery, { autoFetch: true, maxFetch: 50_000 })).records.map((u) => userCache.set((0, core_1.trimTo15)(u.Id), u.Name));
}
};
//# sourceMappingURL=orgQueries.js.map
;