@lark-project/cli
Version:
飞书项目插件开发工具
116 lines (115 loc) • 4.51 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.printCompareResult = exports.runCompare = exports.comparePointInfoMaps = void 0;
const snapshot_1 = require("./snapshot");
const logger_1 = require("../logger");
/**
* Compare two point_info_map objects (both in backend format).
* Operates at the point key level, then recursively diffs field values.
*/
function comparePointInfoMaps(snapshot, remote) {
const snapshotKeys = new Set(Object.keys(snapshot));
const remoteKeys = new Set(Object.keys(remote));
const matched = [];
const missingInRemote = [];
const extraInRemote = [];
const diffs = [];
for (const key of snapshotKeys) {
if (!remoteKeys.has(key)) {
missingInRemote.push(key);
}
else {
const pointDiffs = diffObject(snapshot[key], remote[key], key);
if (pointDiffs.length === 0) {
matched.push(key);
}
else {
diffs.push(...pointDiffs);
}
}
}
for (const key of remoteKeys) {
if (!snapshotKeys.has(key)) {
extraInRemote.push(key);
}
}
return { matched, missingInRemote, extraInRemote, diffs };
}
exports.comparePointInfoMaps = comparePointInfoMaps;
function diffObject(a, b, prefix) {
if (a === b)
return [];
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {
return [{ key: prefix.split('.')[0], field: prefix, snapshotValue: a, remoteValue: b }];
}
if (Array.isArray(a) && Array.isArray(b)) {
const aStr = JSON.stringify(sortDeep(a));
const bStr = JSON.stringify(sortDeep(b));
if (aStr !== bStr) {
return [{ key: prefix.split('.')[0], field: prefix, snapshotValue: a, remoteValue: b }];
}
return [];
}
const result = [];
const allKeys = new Set([...Object.keys(a), ...Object.keys(b)]);
for (const k of allKeys) {
result.push(...diffObject(a[k], b[k], `${prefix}.${k}`));
}
return result;
}
function sortDeep(val) {
if (Array.isArray(val))
return [...val].sort().map(sortDeep);
if (val && typeof val === 'object') {
return Object.fromEntries(Object.entries(val).sort().map(([k, v]) => [k, sortDeep(v)]));
}
return val;
}
function runCompare(caseId, remotePointInfoMap) {
const snapshot = (0, snapshot_1.loadSnapshot)(caseId);
if (!snapshot) {
logger_1.logger.error(`No snapshot found for case ${caseId}. Run update --save-snapshot --case-id ${caseId} first.`);
process.exit(1);
}
const { matched, missingInRemote, extraInRemote, diffs } = comparePointInfoMaps(snapshot, remotePointInfoMap);
const status = missingInRemote.length === 0 && diffs.length === 0
? 'pass'
: matched.length > 0 && diffs.length < matched.length
? 'partial'
: 'fail';
const result = {
caseId,
status,
matched,
missingInRemote,
extraInRemote,
diffs,
snapshotPath: (0, snapshot_1.getSnapshotPath)(caseId),
evaluatedAt: new Date().toISOString(),
};
(0, snapshot_1.saveResult)(caseId, result);
(0, snapshot_1.updateSummary)(caseId, result);
return result;
}
exports.runCompare = runCompare;
function printCompareResult(result) {
const statusEmoji = result.status === 'pass' ? '✅' : result.status === 'partial' ? '⚠️' : '❌';
logger_1.logger.info(`\n${statusEmoji} Compare result for [${result.caseId}]: ${result.status.toUpperCase()}`);
logger_1.logger.info(` Matched keys: ${result.matched.length}`);
if (result.missingInRemote.length > 0) {
logger_1.logger.error(` Missing in remote: ${result.missingInRemote.join(', ')}`);
}
if (result.extraInRemote.length > 0) {
logger_1.logger.info(` Extra in remote: ${result.extraInRemote.join(', ')}`);
}
if (result.diffs.length > 0) {
logger_1.logger.error(` Field diffs (${result.diffs.length}):`);
for (const d of result.diffs) {
logger_1.logger.error(` ${d.field}`);
logger_1.logger.error(` snapshot: ${JSON.stringify(d.snapshotValue)}`);
logger_1.logger.error(` remote: ${JSON.stringify(d.remoteValue)}`);
}
}
logger_1.logger.info(` Results saved to .point-eval/results/${result.caseId}.json`);
}
exports.printCompareResult = printCompareResult;