fix: normalize publish snapshot diff to ignore audit and date noise

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-07-23 11:55:21 +08:00
parent d02e580d91
commit 6ec72d8635

View File

@ -6,11 +6,58 @@ function canonicalKey(key: string): string {
return key.charAt(0).toLowerCase() + key.slice(1)
}
const AUDIT_KEYS = new Set([
'createtime',
'updatetime',
'createby',
'updateby',
'createtimeutc',
'updatetimeutc',
])
function isDefaultDateString(value: string): boolean {
return /^0001-01-01[ T]00:00:00/.test(value.trim())
}
function normalizeScalar(value: unknown): unknown {
if (typeof value !== 'string') return value
if (isDefaultDateString(value)) return undefined
if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}/.test(value)) {
return value.replace('T', ' ').slice(0, 19)
}
return value
}
function sortArrayItems(items: unknown[]): unknown[] {
if (items.length === 0) return items
const first = items[0]
if (first == null || typeof first !== 'object' || Array.isArray(first)) {
return items
}
const record = first as Record<string, unknown>
if ('id' in record) {
return [...items].sort(
(a, b) => Number((a as Record<string, unknown>)?.id ?? 0) - Number((b as Record<string, unknown>)?.id ?? 0)
)
}
if ('serialNumber' in record) {
return [...items].sort(
(a, b) =>
Number((a as Record<string, unknown>)?.serialNumber ?? 0)
- Number((b as Record<string, unknown>)?.serialNumber ?? 0)
)
}
return items
}
/** 递归规范化快照对象,便于语义对比 */
export function normalizeSnapshotForDiff(input: unknown): unknown {
if (input === null || input === undefined) return input
if (input === null || input === undefined) return undefined
if (Array.isArray(input)) {
return input.map((item) => normalizeSnapshotForDiff(item))
const normalized = input
.map((item) => normalizeSnapshotForDiff(item))
.filter((item) => item !== undefined)
return sortArrayItems(normalized)
}
if (typeof input === 'object') {
const record = input as Record<string, unknown>
@ -19,11 +66,15 @@ export function normalizeSnapshotForDiff(input: unknown): unknown {
)
const out: Record<string, unknown> = {}
for (const key of keys) {
out[canonicalKey(key)] = normalizeSnapshotForDiff(record[key])
const ck = canonicalKey(key)
if (AUDIT_KEYS.has(ck)) continue
const val = normalizeSnapshotForDiff(record[key])
if (val === undefined) continue
out[ck] = val
}
return out
}
return input
return normalizeScalar(input)
}
export function parseSnapshotJson(raw: unknown): unknown {
@ -86,6 +137,11 @@ export function computeSnapshotDiff(
try {
const original = normalizeSnapshotForDiff(parseSnapshotJson(originalRaw))
const modified = normalizeSnapshotForDiff(parseSnapshotJson(modifiedRaw))
const originalText = JSON.stringify(original)
const modifiedText = JSON.stringify(modified)
if (originalText === modifiedText) {
return { length: 0, rows: [] }
}
const diff = diffJson(original, modified)
const rows = flattenDiffParts(diff)
const length = diff.filter((item) => item.added || item.removed).length