@emeryld/rrroutes-export 1.0.20 → 1.0.22
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.
- package/package.json +1 -1
- package/tools/finalized-leaves-viewer.html +353 -46
package/package.json
CHANGED
|
@@ -378,6 +378,22 @@
|
|
|
378
378
|
gap: 4px;
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
+
.changelog-commit-separator {
|
|
382
|
+
margin-top: 12px;
|
|
383
|
+
padding-top: 10px;
|
|
384
|
+
border-top: 1px solid var(--accent);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.changelog-commit-separator:first-child {
|
|
388
|
+
margin-top: 0;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.changelog-commit-label {
|
|
392
|
+
color: var(--muted);
|
|
393
|
+
font-weight: 700;
|
|
394
|
+
font-size: 12px;
|
|
395
|
+
}
|
|
396
|
+
|
|
381
397
|
.changelog-diff-line {
|
|
382
398
|
display: flex;
|
|
383
399
|
flex-wrap: wrap;
|
|
@@ -657,6 +673,14 @@
|
|
|
657
673
|
>
|
|
658
674
|
Changelog
|
|
659
675
|
</button>
|
|
676
|
+
<button
|
|
677
|
+
id="tabChangelogGrouped"
|
|
678
|
+
class="field-chip"
|
|
679
|
+
type="button"
|
|
680
|
+
aria-pressed="false"
|
|
681
|
+
>
|
|
682
|
+
Grouped Changelog
|
|
683
|
+
</button>
|
|
660
684
|
</div>
|
|
661
685
|
</div>
|
|
662
686
|
</div>
|
|
@@ -845,6 +869,7 @@
|
|
|
845
869
|
const VIEW_IDS = {
|
|
846
870
|
leaves: 'leaves',
|
|
847
871
|
changelog: 'changelog',
|
|
872
|
+
changelogGrouped: 'changelogGrouped',
|
|
848
873
|
}
|
|
849
874
|
|
|
850
875
|
const VIEWER_MODE = {
|
|
@@ -879,6 +904,12 @@
|
|
|
879
904
|
CHANGELOG_TIMELINE_FIELDS.map((field) => field.id),
|
|
880
905
|
),
|
|
881
906
|
},
|
|
907
|
+
[VIEW_IDS.changelogGrouped]: {
|
|
908
|
+
fieldDefs: CHANGELOG_TIMELINE_FIELDS,
|
|
909
|
+
defaultSelected: new Set(
|
|
910
|
+
CHANGELOG_TIMELINE_FIELDS.map((field) => field.id),
|
|
911
|
+
),
|
|
912
|
+
},
|
|
882
913
|
}
|
|
883
914
|
|
|
884
915
|
const state = {
|
|
@@ -896,6 +927,9 @@
|
|
|
896
927
|
[VIEW_IDS.changelog]: new Set(
|
|
897
928
|
TAB_CONFIG[VIEW_IDS.changelog].defaultSelected,
|
|
898
929
|
),
|
|
930
|
+
[VIEW_IDS.changelogGrouped]: new Set(
|
|
931
|
+
TAB_CONFIG[VIEW_IDS.changelogGrouped].defaultSelected,
|
|
932
|
+
),
|
|
899
933
|
},
|
|
900
934
|
}
|
|
901
935
|
|
|
@@ -921,6 +955,9 @@
|
|
|
921
955
|
const controlsEl = document.querySelector('.controls')
|
|
922
956
|
const tabLeavesBtn = document.getElementById('tabLeaves')
|
|
923
957
|
const tabChangelogBtn = document.getElementById('tabChangelog')
|
|
958
|
+
const tabChangelogGroupedBtn = document.getElementById(
|
|
959
|
+
'tabChangelogGrouped',
|
|
960
|
+
)
|
|
924
961
|
|
|
925
962
|
const URL_PARAM_KEY = 'filters'
|
|
926
963
|
let isHydratingFromUrl = false
|
|
@@ -1758,21 +1795,96 @@
|
|
|
1758
1795
|
return `${type}${schemaFlags(Boolean(entry.nullable), Boolean(entry.optional))}`
|
|
1759
1796
|
}
|
|
1760
1797
|
|
|
1798
|
+
function splitTypeOptions(type) {
|
|
1799
|
+
if (typeof type !== 'string' || !type.includes('|')) return []
|
|
1800
|
+
return type
|
|
1801
|
+
.split('|')
|
|
1802
|
+
.map((item) => item.trim())
|
|
1803
|
+
.filter(Boolean)
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
function hasDefinedLiteral(entry) {
|
|
1807
|
+
return (
|
|
1808
|
+
entry &&
|
|
1809
|
+
typeof entry === 'object' &&
|
|
1810
|
+
Object.prototype.hasOwnProperty.call(entry, 'literal') &&
|
|
1811
|
+
entry.literal !== undefined
|
|
1812
|
+
)
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
function reduceEnumTypeDiff(beforeEntry, afterEntry) {
|
|
1816
|
+
if (!beforeEntry || !afterEntry) return null
|
|
1817
|
+
if (hasDefinedLiteral(beforeEntry) || hasDefinedLiteral(afterEntry)) {
|
|
1818
|
+
return null
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
const beforeOptions = splitTypeOptions(beforeEntry.type)
|
|
1822
|
+
const afterOptions = splitTypeOptions(afterEntry.type)
|
|
1823
|
+
if (beforeOptions.length === 0 || afterOptions.length === 0) return null
|
|
1824
|
+
|
|
1825
|
+
const afterSet = new Set(afterOptions)
|
|
1826
|
+
const beforeSet = new Set(beforeOptions)
|
|
1827
|
+
const beforeOnly = beforeOptions.filter((option) => !afterSet.has(option))
|
|
1828
|
+
const afterOnly = afterOptions.filter((option) => !beforeSet.has(option))
|
|
1829
|
+
if (beforeOnly.length === 0 && afterOnly.length === 0) return null
|
|
1830
|
+
|
|
1831
|
+
const beforeType = `${beforeOnly.join('|') || 'none'}${schemaFlags(
|
|
1832
|
+
Boolean(beforeEntry.nullable),
|
|
1833
|
+
Boolean(beforeEntry.optional),
|
|
1834
|
+
)}`
|
|
1835
|
+
const afterType = `${afterOnly.join('|') || 'none'}${schemaFlags(
|
|
1836
|
+
Boolean(afterEntry.nullable),
|
|
1837
|
+
Boolean(afterEntry.optional),
|
|
1838
|
+
)}`
|
|
1839
|
+
return { beforeType, afterType }
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1761
1842
|
function formatPathLabel(path) {
|
|
1762
1843
|
const basePath = typeof path === 'string' ? path : ''
|
|
1763
1844
|
return basePath
|
|
1764
1845
|
}
|
|
1765
1846
|
|
|
1766
|
-
function
|
|
1847
|
+
function parseSignatureEntry(signature) {
|
|
1767
1848
|
if (typeof signature !== 'string') return null
|
|
1768
1849
|
const typeMatch = signature.match(/(?:^|,\s*)type=([^,]+)/)
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1850
|
+
if (typeMatch) {
|
|
1851
|
+
const nullableMatch = signature.match(
|
|
1852
|
+
/(?:^|,\s*)nullable=(true|false)/,
|
|
1853
|
+
)
|
|
1854
|
+
const optionalMatch = signature.match(
|
|
1855
|
+
/(?:^|,\s*)optional=(true|false)/,
|
|
1856
|
+
)
|
|
1857
|
+
return {
|
|
1858
|
+
type: typeMatch[1],
|
|
1859
|
+
nullable: nullableMatch?.[1] === 'true',
|
|
1860
|
+
optional: optionalMatch?.[1] === 'true',
|
|
1861
|
+
literal: undefined,
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
try {
|
|
1865
|
+
const parsed = JSON.parse(signature)
|
|
1866
|
+
if (!parsed || typeof parsed !== 'object') return null
|
|
1867
|
+
if (typeof parsed.type !== 'string') return null
|
|
1868
|
+
return {
|
|
1869
|
+
type: parsed.type,
|
|
1870
|
+
nullable: Boolean(parsed.nullable),
|
|
1871
|
+
optional: Boolean(parsed.optional),
|
|
1872
|
+
literal: Object.prototype.hasOwnProperty.call(parsed, 'literal')
|
|
1873
|
+
? parsed.literal
|
|
1874
|
+
: undefined,
|
|
1875
|
+
}
|
|
1876
|
+
} catch {
|
|
1877
|
+
return null
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
function parseSignatureTypeLabel(signature) {
|
|
1882
|
+
const entry = parseSignatureEntry(signature)
|
|
1883
|
+
if (!entry) return null
|
|
1884
|
+
return `${entry.type}${schemaFlags(
|
|
1885
|
+
Boolean(entry.nullable),
|
|
1886
|
+
Boolean(entry.optional),
|
|
1887
|
+
)}`
|
|
1776
1888
|
}
|
|
1777
1889
|
|
|
1778
1890
|
function formatSourceTypeLabel(signatures) {
|
|
@@ -1784,6 +1896,18 @@
|
|
|
1784
1896
|
return labels.join(' | ')
|
|
1785
1897
|
}
|
|
1786
1898
|
|
|
1899
|
+
function formatSourceChangedTypes(beforeSignatures, afterSignatures) {
|
|
1900
|
+
if (!Array.isArray(beforeSignatures) || !Array.isArray(afterSignatures)) {
|
|
1901
|
+
return null
|
|
1902
|
+
}
|
|
1903
|
+
if (beforeSignatures.length !== 1 || afterSignatures.length !== 1) {
|
|
1904
|
+
return null
|
|
1905
|
+
}
|
|
1906
|
+
const beforeEntry = parseSignatureEntry(beforeSignatures[0])
|
|
1907
|
+
const afterEntry = parseSignatureEntry(afterSignatures[0])
|
|
1908
|
+
return reduceEnumTypeDiff(beforeEntry, afterEntry)
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1787
1911
|
function schemaDiffOperation(op) {
|
|
1788
1912
|
if (op === 'added') {
|
|
1789
1913
|
return { symbol: '+', word: 'added', className: 'added' }
|
|
@@ -1839,8 +1963,9 @@
|
|
|
1839
1963
|
`removed ${location}: ${JSON.stringify(delta.before || [])}`,
|
|
1840
1964
|
)
|
|
1841
1965
|
}
|
|
1842
|
-
const
|
|
1843
|
-
const
|
|
1966
|
+
const reducedTypes = formatSourceChangedTypes(delta.before, delta.after)
|
|
1967
|
+
const beforeType = reducedTypes?.beforeType || formatSourceTypeLabel(delta.before)
|
|
1968
|
+
const afterType = reducedTypes?.afterType || formatSourceTypeLabel(delta.after)
|
|
1844
1969
|
if (beforeType || afterType) {
|
|
1845
1970
|
return buildSchemaDiffLine(
|
|
1846
1971
|
delta.op,
|
|
@@ -1871,8 +1996,11 @@
|
|
|
1871
1996
|
`removed ${delta.path}: ${formatRouteSchemaEntry(delta.before)}`,
|
|
1872
1997
|
)
|
|
1873
1998
|
}
|
|
1874
|
-
const
|
|
1875
|
-
const
|
|
1999
|
+
const reducedTypes = reduceEnumTypeDiff(delta.before, delta.after)
|
|
2000
|
+
const beforeType =
|
|
2001
|
+
reducedTypes?.beforeType || formatEntryTypeLabel(delta.before) || 'unknown'
|
|
2002
|
+
const afterType =
|
|
2003
|
+
reducedTypes?.afterType || formatEntryTypeLabel(delta.after) || 'unknown'
|
|
1876
2004
|
const pathLabel =
|
|
1877
2005
|
formatPathLabel(delta.path) || delta.path
|
|
1878
2006
|
return buildSchemaDiffLine(delta.op, beforeType, pathLabel, afterType)
|
|
@@ -1899,10 +2027,14 @@
|
|
|
1899
2027
|
function eventVisualByType(type) {
|
|
1900
2028
|
switch (type) {
|
|
1901
2029
|
case 'route_added':
|
|
1902
|
-
return {
|
|
2030
|
+
return {
|
|
2031
|
+
actionText: 'added route',
|
|
2032
|
+
actionClass: 'event-action-added',
|
|
2033
|
+
icon: 'route',
|
|
2034
|
+
}
|
|
1903
2035
|
case 'route_removed':
|
|
1904
2036
|
return {
|
|
1905
|
-
actionText: 'removed',
|
|
2037
|
+
actionText: 'removed route',
|
|
1906
2038
|
actionClass: 'event-action-removed',
|
|
1907
2039
|
icon: 'route',
|
|
1908
2040
|
}
|
|
@@ -1919,18 +2051,22 @@
|
|
|
1919
2051
|
icon: 'config',
|
|
1920
2052
|
}
|
|
1921
2053
|
case 'source_object_added':
|
|
1922
|
-
return {
|
|
2054
|
+
return {
|
|
2055
|
+
actionText: 'added source object',
|
|
2056
|
+
actionClass: 'event-action-added',
|
|
2057
|
+
icon: 'source',
|
|
2058
|
+
}
|
|
1923
2059
|
case 'source_object_removed':
|
|
1924
2060
|
return {
|
|
1925
|
-
actionText: 'removed',
|
|
2061
|
+
actionText: 'removed source object',
|
|
1926
2062
|
actionClass: 'event-action-removed',
|
|
1927
2063
|
icon: 'source',
|
|
1928
2064
|
}
|
|
1929
2065
|
case 'source_schema_changed':
|
|
1930
2066
|
return {
|
|
1931
|
-
actionText: 'modified
|
|
2067
|
+
actionText: 'modified schema',
|
|
1932
2068
|
actionClass: 'event-action-modified',
|
|
1933
|
-
icon: '
|
|
2069
|
+
icon: 'schema',
|
|
1934
2070
|
}
|
|
1935
2071
|
default:
|
|
1936
2072
|
return {
|
|
@@ -2022,6 +2158,18 @@
|
|
|
2022
2158
|
),
|
|
2023
2159
|
)
|
|
2024
2160
|
}
|
|
2161
|
+
if (
|
|
2162
|
+
Number.isInteger(options?.item?.dedupedRouteCount) &&
|
|
2163
|
+
options.item.dedupedRouteCount > 0
|
|
2164
|
+
) {
|
|
2165
|
+
card.appendChild(
|
|
2166
|
+
el(
|
|
2167
|
+
'div',
|
|
2168
|
+
'meta',
|
|
2169
|
+
`deduped route schema events: ${options.item.dedupedRouteCount}`,
|
|
2170
|
+
),
|
|
2171
|
+
)
|
|
2172
|
+
}
|
|
2025
2173
|
return card
|
|
2026
2174
|
}
|
|
2027
2175
|
|
|
@@ -2038,6 +2186,34 @@
|
|
|
2038
2186
|
.join(' - ')
|
|
2039
2187
|
}
|
|
2040
2188
|
|
|
2189
|
+
function renderCommitSeparator(commitSha, commitBySha) {
|
|
2190
|
+
const box = el('div', 'changelog-commit-separator')
|
|
2191
|
+
const commit = commitBySha.get(commitSha)
|
|
2192
|
+
const commitDateTime = formatCommitDateTime(commit?.authorDate)
|
|
2193
|
+
const label = `commit ${String(commitSha || '').slice(0, 12)}`
|
|
2194
|
+
const meta = [commitDateTime, commit?.authorName || null, commit?.subject || null]
|
|
2195
|
+
.filter(Boolean)
|
|
2196
|
+
.join(' - ')
|
|
2197
|
+
box.appendChild(el('div', 'changelog-commit-label mono', label))
|
|
2198
|
+
if (meta) {
|
|
2199
|
+
box.appendChild(el('div', 'meta', meta))
|
|
2200
|
+
}
|
|
2201
|
+
return box
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
function renderChangelogWithCommitSeparators(items, commitBySha, renderItem) {
|
|
2205
|
+
if (!Array.isArray(items) || items.length === 0) return
|
|
2206
|
+
let previousCommitSha = null
|
|
2207
|
+
items.forEach((item) => {
|
|
2208
|
+
const currentCommitSha = item?.event?.commitSha || null
|
|
2209
|
+
if (currentCommitSha !== previousCommitSha) {
|
|
2210
|
+
resultsEl.appendChild(renderCommitSeparator(currentCommitSha, commitBySha))
|
|
2211
|
+
previousCommitSha = currentCommitSha
|
|
2212
|
+
}
|
|
2213
|
+
resultsEl.appendChild(renderItem(item))
|
|
2214
|
+
})
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2041
2217
|
function renderChangelogEventLines(item, commitBySha) {
|
|
2042
2218
|
const event = item.event
|
|
2043
2219
|
const row = el('div', 'changelog-line-item')
|
|
@@ -2072,6 +2248,18 @@
|
|
|
2072
2248
|
),
|
|
2073
2249
|
)
|
|
2074
2250
|
}
|
|
2251
|
+
if (
|
|
2252
|
+
Number.isInteger(item?.dedupedRouteCount) &&
|
|
2253
|
+
item.dedupedRouteCount > 0
|
|
2254
|
+
) {
|
|
2255
|
+
row.appendChild(
|
|
2256
|
+
el(
|
|
2257
|
+
'div',
|
|
2258
|
+
'meta mono',
|
|
2259
|
+
`deduped route schema events: ${item.dedupedRouteCount}`,
|
|
2260
|
+
),
|
|
2261
|
+
)
|
|
2262
|
+
}
|
|
2075
2263
|
|
|
2076
2264
|
return row
|
|
2077
2265
|
}
|
|
@@ -2103,6 +2291,60 @@
|
|
|
2103
2291
|
)
|
|
2104
2292
|
}
|
|
2105
2293
|
|
|
2294
|
+
function schemaEntrySignature(entry) {
|
|
2295
|
+
if (!entry || typeof entry !== 'object') return ''
|
|
2296
|
+
return JSON.stringify({
|
|
2297
|
+
type: typeof entry.type === 'string' ? entry.type : 'unknown',
|
|
2298
|
+
nullable: Boolean(entry.nullable),
|
|
2299
|
+
optional: Boolean(entry.optional),
|
|
2300
|
+
literal: entry.literal,
|
|
2301
|
+
})
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
function normalizeSignatureToken(signature) {
|
|
2305
|
+
if (typeof signature !== 'string') return ''
|
|
2306
|
+
const parsed = parseSignatureEntry(signature)
|
|
2307
|
+
if (!parsed) return signature
|
|
2308
|
+
return schemaEntrySignature(parsed)
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
function normalizedSchemaDeltaParts(delta) {
|
|
2312
|
+
if (!delta || typeof delta !== 'object') return null
|
|
2313
|
+
const op = String(delta.op || 'changed')
|
|
2314
|
+
if ('path' in delta) {
|
|
2315
|
+
const location = String(delta.path || '')
|
|
2316
|
+
const before = delta.before ? [schemaEntrySignature(delta.before)] : []
|
|
2317
|
+
const after = delta.after ? [schemaEntrySignature(delta.after)] : []
|
|
2318
|
+
return { op, location, before, after }
|
|
2319
|
+
}
|
|
2320
|
+
if ('section' in delta) {
|
|
2321
|
+
const location = `${delta.section}.${delta.path}`
|
|
2322
|
+
const before = Array.isArray(delta.before)
|
|
2323
|
+
? delta.before.map((item) => normalizeSignatureToken(item)).filter(Boolean)
|
|
2324
|
+
: []
|
|
2325
|
+
const after = Array.isArray(delta.after)
|
|
2326
|
+
? delta.after.map((item) => normalizeSignatureToken(item)).filter(Boolean)
|
|
2327
|
+
: []
|
|
2328
|
+
before.sort()
|
|
2329
|
+
after.sort()
|
|
2330
|
+
return { op, location, before, after }
|
|
2331
|
+
}
|
|
2332
|
+
return null
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
function schemaDiffFingerprint(schemaDiff) {
|
|
2336
|
+
if (!Array.isArray(schemaDiff) || schemaDiff.length === 0) return ''
|
|
2337
|
+
const lines = schemaDiff
|
|
2338
|
+
.map((delta) => normalizedSchemaDeltaParts(delta))
|
|
2339
|
+
.filter(Boolean)
|
|
2340
|
+
.map(
|
|
2341
|
+
(part) =>
|
|
2342
|
+
`${part.op}|${part.location}|${part.before.join('&')}|${part.after.join('&')}`,
|
|
2343
|
+
)
|
|
2344
|
+
.sort()
|
|
2345
|
+
return lines.join('||')
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2106
2348
|
function buildChronologicalEvents(payload) {
|
|
2107
2349
|
if (!payload) return []
|
|
2108
2350
|
const commitBySha = new Map(
|
|
@@ -2113,9 +2355,43 @@
|
|
|
2113
2355
|
)
|
|
2114
2356
|
const rows = []
|
|
2115
2357
|
let sequence = 0
|
|
2358
|
+
const sourceSchemaCoverage = new Map()
|
|
2359
|
+
|
|
2360
|
+
Object.entries(payload.bySourceObject || {}).forEach(
|
|
2361
|
+
([sourceObjectId, events]) => {
|
|
2362
|
+
;(events || []).forEach((event) => {
|
|
2363
|
+
if (event?.type !== 'source_schema_changed') return
|
|
2364
|
+
const fingerprint = schemaDiffFingerprint(event.schemaDiff)
|
|
2365
|
+
if (!fingerprint) return
|
|
2366
|
+
const key = `${event.commitSha}|${fingerprint}`
|
|
2367
|
+
let coverage = sourceSchemaCoverage.get(key)
|
|
2368
|
+
if (!coverage) {
|
|
2369
|
+
coverage = {
|
|
2370
|
+
sourceObjectIds: new Set(),
|
|
2371
|
+
impactedRoutes: new Set(),
|
|
2372
|
+
dedupedRouteKeys: new Set(),
|
|
2373
|
+
}
|
|
2374
|
+
sourceSchemaCoverage.set(key, coverage)
|
|
2375
|
+
}
|
|
2376
|
+
coverage.sourceObjectIds.add(sourceObjectId)
|
|
2377
|
+
;(event.impactedRoutes || []).forEach((routeKey) => {
|
|
2378
|
+
coverage.impactedRoutes.add(routeKey)
|
|
2379
|
+
})
|
|
2380
|
+
})
|
|
2381
|
+
},
|
|
2382
|
+
)
|
|
2116
2383
|
|
|
2117
2384
|
Object.entries(payload.byRoute || {}).forEach(([routeKey, events]) => {
|
|
2118
2385
|
;(events || []).forEach((event) => {
|
|
2386
|
+
if (event?.type === 'schema_changed') {
|
|
2387
|
+
const fingerprint = schemaDiffFingerprint(event.schemaDiff)
|
|
2388
|
+
const key = `${event.commitSha}|${fingerprint}`
|
|
2389
|
+
const coverage = sourceSchemaCoverage.get(key)
|
|
2390
|
+
if (coverage && coverage.impactedRoutes.has(routeKey)) {
|
|
2391
|
+
coverage.dedupedRouteKeys.add(routeKey)
|
|
2392
|
+
return
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2119
2395
|
rows.push({
|
|
2120
2396
|
eventKind: 'route',
|
|
2121
2397
|
routeKey,
|
|
@@ -2131,10 +2407,21 @@
|
|
|
2131
2407
|
Object.entries(payload.bySourceObject || {}).forEach(
|
|
2132
2408
|
([sourceObjectId, events]) => {
|
|
2133
2409
|
;(events || []).forEach((event) => {
|
|
2410
|
+
const fingerprint =
|
|
2411
|
+
event?.type === 'source_schema_changed'
|
|
2412
|
+
? schemaDiffFingerprint(event.schemaDiff)
|
|
2413
|
+
: ''
|
|
2414
|
+
const coverage = sourceSchemaCoverage.get(
|
|
2415
|
+
`${event.commitSha}|${fingerprint}`,
|
|
2416
|
+
)
|
|
2134
2417
|
rows.push({
|
|
2135
2418
|
eventKind: 'source',
|
|
2136
2419
|
sourceObjectId,
|
|
2137
2420
|
displayName: event.displayName || sourceObjectId,
|
|
2421
|
+
dedupedRouteCount:
|
|
2422
|
+
event?.type === 'source_schema_changed'
|
|
2423
|
+
? coverage?.dedupedRouteKeys.size || 0
|
|
2424
|
+
: 0,
|
|
2138
2425
|
event,
|
|
2139
2426
|
commit: commitBySha.get(event.commitSha),
|
|
2140
2427
|
commitSort: commitTimestamp(commitBySha.get(event.commitSha)),
|
|
@@ -2158,7 +2445,10 @@
|
|
|
2158
2445
|
function changelogItemsByTab(tabId) {
|
|
2159
2446
|
const payload = state.changelogPayload
|
|
2160
2447
|
if (!payload) return []
|
|
2161
|
-
if (
|
|
2448
|
+
if (
|
|
2449
|
+
tabId === VIEW_IDS.changelog ||
|
|
2450
|
+
tabId === VIEW_IDS.changelogGrouped
|
|
2451
|
+
) {
|
|
2162
2452
|
return buildChronologicalEvents(payload)
|
|
2163
2453
|
}
|
|
2164
2454
|
return []
|
|
@@ -2187,6 +2477,10 @@
|
|
|
2187
2477
|
function renderTabButtons() {
|
|
2188
2478
|
setPressed(tabLeavesBtn, state.activeTab === VIEW_IDS.leaves)
|
|
2189
2479
|
setPressed(tabChangelogBtn, state.activeTab === VIEW_IDS.changelog)
|
|
2480
|
+
setPressed(
|
|
2481
|
+
tabChangelogGroupedBtn,
|
|
2482
|
+
state.activeTab === VIEW_IDS.changelogGrouped,
|
|
2483
|
+
)
|
|
2190
2484
|
tabLeavesBtn.style.display = state.availableTabs.has(VIEW_IDS.leaves)
|
|
2191
2485
|
? ''
|
|
2192
2486
|
: 'none'
|
|
@@ -2195,6 +2489,11 @@
|
|
|
2195
2489
|
)
|
|
2196
2490
|
? ''
|
|
2197
2491
|
: 'none'
|
|
2492
|
+
tabChangelogGroupedBtn.style.display = state.availableTabs.has(
|
|
2493
|
+
VIEW_IDS.changelogGrouped,
|
|
2494
|
+
)
|
|
2495
|
+
? ''
|
|
2496
|
+
: 'none'
|
|
2198
2497
|
const isLeavesTab = state.activeTab === VIEW_IDS.leaves
|
|
2199
2498
|
coreFieldsBtn.style.display = isLeavesTab ? '' : 'none'
|
|
2200
2499
|
schemasOnlyFieldsBtn.style.display = isLeavesTab ? '' : 'none'
|
|
@@ -2247,30 +2546,26 @@
|
|
|
2247
2546
|
commit,
|
|
2248
2547
|
]),
|
|
2249
2548
|
)
|
|
2250
|
-
if (
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2549
|
+
if (filtered.length === 0) {
|
|
2550
|
+
resultsEl.appendChild(el('div', 'empty', 'No matches.'))
|
|
2551
|
+
} else if (state.activeTab === VIEW_IDS.changelog) {
|
|
2552
|
+
renderChangelogWithCommitSeparators(filtered, commitBySha, (item) =>
|
|
2553
|
+
renderChangelogEventLines(item, commitBySha),
|
|
2255
2554
|
)
|
|
2256
2555
|
} else {
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
(
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
return details
|
|
2271
|
-
},
|
|
2272
|
-
'No matches.',
|
|
2273
|
-
)
|
|
2556
|
+
renderChangelogWithCommitSeparators(filtered, commitBySha, (item) => {
|
|
2557
|
+
const details = el('details', 'leaf')
|
|
2558
|
+
const summary = el('summary')
|
|
2559
|
+
summary.appendChild(renderEventTitle(item))
|
|
2560
|
+
details.appendChild(summary)
|
|
2561
|
+
details.appendChild(
|
|
2562
|
+
renderEventCard(item.event, commitBySha, {
|
|
2563
|
+
showTitle: false,
|
|
2564
|
+
item,
|
|
2565
|
+
}),
|
|
2566
|
+
)
|
|
2567
|
+
return details
|
|
2568
|
+
})
|
|
2274
2569
|
}
|
|
2275
2570
|
}
|
|
2276
2571
|
syncFilterStateToUrl()
|
|
@@ -2296,7 +2591,8 @@
|
|
|
2296
2591
|
{
|
|
2297
2592
|
id: 'tabFields',
|
|
2298
2593
|
label:
|
|
2299
|
-
state.activeTab === VIEW_IDS.changelog
|
|
2594
|
+
state.activeTab === VIEW_IDS.changelog ||
|
|
2595
|
+
state.activeTab === VIEW_IDS.changelogGrouped
|
|
2300
2596
|
? 'Changelog fields'
|
|
2301
2597
|
: 'Source fields',
|
|
2302
2598
|
fieldIds: fieldDefs.map((field) => field.id),
|
|
@@ -2484,7 +2780,8 @@
|
|
|
2484
2780
|
isHydratingFromUrl = true
|
|
2485
2781
|
if (
|
|
2486
2782
|
parsed.activeTab === VIEW_IDS.leaves ||
|
|
2487
|
-
parsed.activeTab === VIEW_IDS.changelog
|
|
2783
|
+
parsed.activeTab === VIEW_IDS.changelog ||
|
|
2784
|
+
parsed.activeTab === VIEW_IDS.changelogGrouped
|
|
2488
2785
|
) {
|
|
2489
2786
|
state.activeTab = parsed.activeTab
|
|
2490
2787
|
}
|
|
@@ -2573,12 +2870,19 @@
|
|
|
2573
2870
|
}
|
|
2574
2871
|
if (state.changelogPayload) {
|
|
2575
2872
|
state.availableTabs.add(VIEW_IDS.changelog)
|
|
2873
|
+
if (state.viewerMode === VIEWER_MODE.bundle) {
|
|
2874
|
+
state.availableTabs.add(VIEW_IDS.changelogGrouped)
|
|
2875
|
+
}
|
|
2576
2876
|
}
|
|
2577
2877
|
|
|
2578
2878
|
if (!state.availableTabs.has(state.activeTab)) {
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2879
|
+
if (state.availableTabs.has(VIEW_IDS.leaves)) {
|
|
2880
|
+
state.activeTab = VIEW_IDS.leaves
|
|
2881
|
+
} else if (state.availableTabs.has(VIEW_IDS.changelog)) {
|
|
2882
|
+
state.activeTab = VIEW_IDS.changelog
|
|
2883
|
+
} else {
|
|
2884
|
+
state.activeTab = VIEW_IDS.changelogGrouped
|
|
2885
|
+
}
|
|
2582
2886
|
}
|
|
2583
2887
|
|
|
2584
2888
|
if (state.leavesPayload && state.changelogPayload) {
|
|
@@ -2641,6 +2945,9 @@
|
|
|
2641
2945
|
tabChangelogBtn.addEventListener('click', () =>
|
|
2642
2946
|
setActiveTab(VIEW_IDS.changelog),
|
|
2643
2947
|
)
|
|
2948
|
+
tabChangelogGroupedBtn.addEventListener('click', () =>
|
|
2949
|
+
setActiveTab(VIEW_IDS.changelogGrouped),
|
|
2950
|
+
)
|
|
2644
2951
|
|
|
2645
2952
|
selectAllFieldsBtn.addEventListener('click', () =>
|
|
2646
2953
|
setFieldSelection(new Set(currentFieldDefs().map((field) => field.id))),
|