Repository navigation
Expand file tree
/
Copy pathcompare-systems.js
More file actions
127 lines (108 loc) · 4.33 KB
/
Copy pathcompare-systems.js
File metadata and controls
127 lines (108 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env node
import { writeFileSync, mkdirSync, existsSync } from 'fs';
import { join } from 'path';
const IMS_URL = process.env.IMS_BASE_URL || 'https://imsprod-approuter.cfapps.us30.hana.ondemand.com';
const CAP_URL = process.env.CAP_BASE_URL || 'http://localhost:4004';
const OUTPUT_DIR = '.comparison-results';
const AUTH_TOKEN = process.env.IMS_AUTH_TOKEN;
const COMPARISON_ENDPOINTS = [
{ name: 'tutorials-list', ims: '/api/tutorials', cap: '/api/Tutorials' },
{ name: 'missions-list', ims: '/api/missions', cap: '/api/Missions?$select=legacyId,title,status' },
{ name: 'events-list', ims: '/api/events', cap: '/admin/Events' },
{ name: 'tags-list', ims: '/api/tags', cap: '/admin/Tags' }
];
async function fetchEndpoint(baseUrl, path) {
const url = `${baseUrl}${path}`;
const headers = AUTH_TOKEN ? { Authorization: `Bearer ${AUTH_TOKEN}` } : {};
const res = await fetch(url, { headers });
if (!res.ok) return { error: `${res.status} ${res.statusText}`, url };
return res.json();
}
function normalizeForComparison(data) {
const records = Array.isArray(data) ? data
: (data.value || data.content || data._embedded?.items || []);
return records.map(r => {
const normalized = {};
const keys = Object.keys(r).filter(k =>
!k.startsWith('_') && !k.startsWith('@') &&
!['ID', 'createdAt', 'modifiedAt', 'createdBy', 'modifiedBy'].includes(k)
).sort();
for (const key of keys) normalized[key] = r[key];
return normalized;
}).sort((a, b) => (a.legacyId || 0) - (b.legacyId || 0));
}
function diffRecords(imsRecords, capRecords) {
const diffs = [];
const imsMap = new Map(imsRecords.map(r => [r.legacyId, r]));
const capMap = new Map(capRecords.map(r => [r.legacyId, r]));
for (const [id, imsRec] of imsMap) {
const capRec = capMap.get(id);
if (!capRec) {
diffs.push({ type: 'missing_in_cap', legacyId: id });
} else {
const fieldDiffs = [];
for (const key of Object.keys(imsRec)) {
if (JSON.stringify(imsRec[key]) !== JSON.stringify(capRec[key])) {
fieldDiffs.push({ field: key, ims: imsRec[key], cap: capRec[key] });
}
}
if (fieldDiffs.length > 0) {
diffs.push({ type: 'field_mismatch', legacyId: id, fields: fieldDiffs });
}
}
}
for (const [id] of capMap) {
if (!imsMap.has(id)) {
diffs.push({ type: 'extra_in_cap', legacyId: id });
}
}
return diffs;
}
async function runComparisons() {
if (!existsSync(OUTPUT_DIR)) mkdirSync(OUTPUT_DIR, { recursive: true });
console.log(`Comparing: ${IMS_URL} ↔ ${CAP_URL}\n`);
const results = [];
for (const endpoint of COMPARISON_ENDPOINTS) {
console.log(`${endpoint.name}...`);
const [imsData, capData] = await Promise.all([
fetchEndpoint(IMS_URL, endpoint.ims),
fetchEndpoint(CAP_URL, endpoint.cap)
]);
if (imsData.error || capData.error) {
const result = { endpoint: endpoint.name, status: 'ERROR', imsError: imsData.error, capError: capData.error };
results.push(result);
console.log(` ✗ Error: IMS=${imsData.error || 'OK'}, CAP=${capData.error || 'OK'}`);
continue;
}
const imsNormalized = normalizeForComparison(imsData);
const capNormalized = normalizeForComparison(capData);
const diffs = diffRecords(imsNormalized, capNormalized);
const result = {
endpoint: endpoint.name,
status: diffs.length === 0 ? 'MATCH' : 'DIFF',
imsCount: imsNormalized.length,
capCount: capNormalized.length,
diffs: diffs.slice(0, 20)
};
results.push(result);
if (diffs.length === 0) {
console.log(` ✓ Match (${imsNormalized.length} records)`);
} else {
console.log(` ✗ ${diffs.length} differences (IMS: ${imsNormalized.length}, CAP: ${capNormalized.length})`);
}
}
const reportPath = join(OUTPUT_DIR, `comparison-${new Date().toISOString().slice(0, 10)}.json`);
writeFileSync(reportPath, JSON.stringify(results, null, 2));
console.log(`\nReport saved to ${reportPath}`);
const failed = results.filter(r => r.status !== 'MATCH');
if (failed.length > 0) {
console.log(`\n${failed.length}/${results.length} endpoints have differences.`);
process.exit(1);
} else {
console.log(`\nAll ${results.length} endpoints match.`);
}
}
runComparisons().catch(err => {
console.error('Comparison failed:', err.message);
process.exit(1);
});