@emeryld/rrroutes-export 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -648,6 +648,7 @@
648
648
  const state = {
649
649
  payload: null,
650
650
  leaves: [],
651
+ mode: 'snapshot',
651
652
  selectedFieldIds: new Set(SEARCH_FIELDS.map((field) => field.id)),
652
653
  }
653
654
 
@@ -667,6 +668,7 @@
667
668
  const resetFiltersBtn = document.getElementById('resetFilters')
668
669
  const statusEl = document.getElementById('status')
669
670
  const resultsEl = document.getElementById('results')
671
+ const controlsEl = document.querySelector('.controls')
670
672
 
671
673
  const URL_PARAM_KEY = 'filters'
672
674
  let isHydratingFromUrl = false
@@ -1306,7 +1308,115 @@
1306
1308
  return details
1307
1309
  }
1308
1310
 
1311
+ function isChangelogPayload(value) {
1312
+ return (
1313
+ value &&
1314
+ value.kind === 'finalized-leaves-changelog' &&
1315
+ Array.isArray(value.commits)
1316
+ )
1317
+ }
1318
+
1319
+ function renderChangelogPayload(payload) {
1320
+ state.mode = 'changelog'
1321
+ state.payload = payload
1322
+ state.leaves = []
1323
+
1324
+ if (controlsEl) {
1325
+ controlsEl.style.display = 'none'
1326
+ }
1327
+
1328
+ const commitBySha = new Map(
1329
+ (payload.commits || []).map((commit) => [commit.sha, commit]),
1330
+ )
1331
+ const routeEntries = Object.entries(payload.byRoute || {}).sort(
1332
+ ([a], [b]) => a.localeCompare(b),
1333
+ )
1334
+ const sourceEntries = Object.entries(payload.bySourceObject || {}).sort(
1335
+ ([a], [b]) => a.localeCompare(b),
1336
+ )
1337
+
1338
+ statusEl.textContent = `Loaded changelog payload with ${payload.commits.length} commits.`
1339
+ resultsEl.innerHTML = ''
1340
+
1341
+ const tabs = el('div', 'chips')
1342
+ const byRouteBtn = el('button', 'chip chip-btn', 'By Route')
1343
+ const bySourceBtn = el('button', 'chip chip-btn', 'By Source Object')
1344
+ byRouteBtn.type = 'button'
1345
+ bySourceBtn.type = 'button'
1346
+ tabs.appendChild(byRouteBtn)
1347
+ tabs.appendChild(bySourceBtn)
1348
+ resultsEl.appendChild(tabs)
1349
+
1350
+ const view = el('div')
1351
+ resultsEl.appendChild(view)
1352
+
1353
+ const renderEventDetails = (event) => {
1354
+ const card = el('div', 'leaf-content')
1355
+ const commit = commitBySha.get(event.commitSha)
1356
+ card.appendChild(
1357
+ el(
1358
+ 'div',
1359
+ 'meta',
1360
+ `${event.commitSha.slice(0, 12)}${commit?.subject ? ` - ${commit.subject}` : ''}`,
1361
+ ),
1362
+ )
1363
+ card.appendChild(el('div', 'mono', event.type))
1364
+ if (Array.isArray(event.schemaDiff) && event.schemaDiff.length > 0) {
1365
+ card.appendChild(el('div', 'meta', `schema changes: ${event.schemaDiff.length}`))
1366
+ }
1367
+ if (Array.isArray(event.cfgDiff) && event.cfgDiff.length > 0) {
1368
+ card.appendChild(el('div', 'meta', `cfg changes: ${event.cfgDiff.length}`))
1369
+ }
1370
+ if (Array.isArray(event.impactedRoutes) && event.impactedRoutes.length > 0) {
1371
+ card.appendChild(
1372
+ el('div', 'meta', `impacted routes: ${event.impactedRoutes.length}`),
1373
+ )
1374
+ }
1375
+ return card
1376
+ }
1377
+
1378
+ const renderByRoute = () => {
1379
+ view.innerHTML = ''
1380
+ if (routeEntries.length === 0) {
1381
+ view.appendChild(el('div', 'empty', 'No route changes found in this range.'))
1382
+ return
1383
+ }
1384
+
1385
+ routeEntries.forEach(([routeKey, events]) => {
1386
+ const details = el('details', 'leaf')
1387
+ details.appendChild(el('summary', '', `${routeKey} (${events.length})`))
1388
+ events.forEach((event) => details.appendChild(renderEventDetails(event)))
1389
+ view.appendChild(details)
1390
+ })
1391
+ }
1392
+
1393
+ const renderBySource = () => {
1394
+ view.innerHTML = ''
1395
+ if (sourceEntries.length === 0) {
1396
+ view.appendChild(
1397
+ el('div', 'empty', 'No source-object changes found in this range.'),
1398
+ )
1399
+ return
1400
+ }
1401
+
1402
+ sourceEntries.forEach(([sourceId, events]) => {
1403
+ const details = el('details', 'leaf')
1404
+ const display = events[0]?.displayName || sourceId
1405
+ details.appendChild(el('summary', '', `${display} (${events.length})`))
1406
+ events.forEach((event) => details.appendChild(renderEventDetails(event)))
1407
+ view.appendChild(details)
1408
+ })
1409
+ }
1410
+
1411
+ byRouteBtn.addEventListener('click', renderByRoute)
1412
+ bySourceBtn.addEventListener('click', renderBySource)
1413
+ renderByRoute()
1414
+ }
1415
+
1309
1416
  function renderResults() {
1417
+ if (state.mode === 'changelog') {
1418
+ return
1419
+ }
1310
1420
  const engine = createSearchEngine(searchInput.value.trim(), {
1311
1421
  caseSensitive: isPressed(caseSensitiveToggle),
1312
1422
  regex: isPressed(regexSearchToggle),
@@ -1529,10 +1639,20 @@
1529
1639
  async function handleFile(file) {
1530
1640
  const text = await file.text()
1531
1641
  const parsed = JSON.parse(text)
1642
+ if (isChangelogPayload(parsed)) {
1643
+ renderChangelogPayload(parsed)
1644
+ return
1645
+ }
1532
1646
  if (!parsed || !Array.isArray(parsed.leaves)) {
1533
- throw new Error('Invalid export file: expected top-level "leaves" array.')
1647
+ throw new Error(
1648
+ 'Invalid export file: expected top-level "leaves" array or changelog payload.',
1649
+ )
1534
1650
  }
1535
1651
 
1652
+ state.mode = 'snapshot'
1653
+ if (controlsEl) {
1654
+ controlsEl.style.display = ''
1655
+ }
1536
1656
  state.payload = parsed
1537
1657
  state.leaves = parsed.leaves
1538
1658
  renderResults()
@@ -1540,8 +1660,16 @@
1540
1660
 
1541
1661
  function initializeFromBakedPayload() {
1542
1662
  const baked = window.__FINALIZED_LEAVES_PAYLOAD
1663
+ if (isChangelogPayload(baked)) {
1664
+ renderChangelogPayload(baked)
1665
+ return
1666
+ }
1543
1667
  if (!baked || !Array.isArray(baked.leaves)) return
1544
1668
 
1669
+ state.mode = 'snapshot'
1670
+ if (controlsEl) {
1671
+ controlsEl.style.display = ''
1672
+ }
1545
1673
  state.payload = baked
1546
1674
  state.leaves = baked.leaves
1547
1675
  statusEl.textContent = `Loaded baked payload with ${state.leaves.length} routes.`