@emeryld/rrroutes-contract 2.7.5 → 2.7.6
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/README.md +19 -1
- package/bin/rrroutes-export-finalized-leaves.mjs +14 -0
- package/dist/export/defaultViewerTemplate.d.ts +1 -1
- package/dist/export/exportFinalizedLeaves.cli.d.ts +2 -0
- package/dist/export/exportFinalizedLeaves.d.ts +14 -0
- package/dist/export/extractLeafSourceByAst.d.ts +30 -0
- package/dist/export/index.d.ts +1 -0
- package/dist/index.cjs +540 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +539 -38
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -2
- package/tools/finalized-leaves-viewer.html +164 -7
|
@@ -312,6 +312,10 @@
|
|
|
312
312
|
<option value="exact">exact</option>
|
|
313
313
|
</select>
|
|
314
314
|
</label>
|
|
315
|
+
<label class="field-item">
|
|
316
|
+
<input id="schemaRowsMatchOnly" type="checkbox" />
|
|
317
|
+
<span>schema rows match filter</span>
|
|
318
|
+
</label>
|
|
315
319
|
</div>
|
|
316
320
|
|
|
317
321
|
<div id="fieldCheckboxes" class="field-row"></div>
|
|
@@ -346,6 +350,31 @@
|
|
|
346
350
|
{ id: 'tags', label: 'tags', get: (leaf) => leaf.cfg?.tags || [] },
|
|
347
351
|
{ id: 'stability', label: 'stability', get: (leaf) => [leaf.cfg?.stability] },
|
|
348
352
|
{ id: 'docsMeta', label: 'docsMeta', get: (leaf) => [leaf.cfg?.docsMeta] },
|
|
353
|
+
{
|
|
354
|
+
id: 'sourceDefinition',
|
|
355
|
+
label: 'source definition',
|
|
356
|
+
get: (leaf, schemaFlatByLeaf, payload) => {
|
|
357
|
+
const source = payload?.sourceByLeaf?.[leaf.key]?.definition
|
|
358
|
+
if (!source) return []
|
|
359
|
+
return [`${source.file}:${source.line}:${source.column}`]
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
id: 'sourceSchemas',
|
|
364
|
+
label: 'source schemas',
|
|
365
|
+
get: (leaf, schemaFlatByLeaf, payload) => {
|
|
366
|
+
const schemas = payload?.sourceByLeaf?.[leaf.key]?.schemas
|
|
367
|
+
if (!schemas || typeof schemas !== 'object') return []
|
|
368
|
+
return Object.values(schemas).flatMap((schema) => {
|
|
369
|
+
if (!schema || typeof schema !== 'object') return []
|
|
370
|
+
const tokens = []
|
|
371
|
+
if (schema.sourceName) tokens.push(schema.sourceName)
|
|
372
|
+
if (schema.tag) tokens.push(schema.tag)
|
|
373
|
+
tokens.push(`${schema.file}:${schema.line}:${schema.column}`)
|
|
374
|
+
return tokens
|
|
375
|
+
})
|
|
376
|
+
},
|
|
377
|
+
},
|
|
349
378
|
{
|
|
350
379
|
id: 'types',
|
|
351
380
|
label: 'types',
|
|
@@ -390,6 +419,7 @@
|
|
|
390
419
|
const caseSensitiveInput = document.getElementById('caseSensitive')
|
|
391
420
|
const regexSearchInput = document.getElementById('regexSearch')
|
|
392
421
|
const typeMatchModeInput = document.getElementById('typeMatchMode')
|
|
422
|
+
const schemaRowsMatchOnlyInput = document.getElementById('schemaRowsMatchOnly')
|
|
393
423
|
const fieldCheckboxes = document.getElementById('fieldCheckboxes')
|
|
394
424
|
const activeFilterChips = document.getElementById('activeFilterChips')
|
|
395
425
|
const selectAllFieldsBtn = document.getElementById('selectAllFields')
|
|
@@ -557,6 +587,63 @@
|
|
|
557
587
|
return Array.from(tokens)
|
|
558
588
|
}
|
|
559
589
|
|
|
590
|
+
function schemaEntryTokens(path, info) {
|
|
591
|
+
const tokens = new Set()
|
|
592
|
+
|
|
593
|
+
if (path) {
|
|
594
|
+
tokens.add(path)
|
|
595
|
+
path.split('.').forEach((segment) => {
|
|
596
|
+
if (segment) tokens.add(segment)
|
|
597
|
+
})
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (info && typeof info === 'object') {
|
|
601
|
+
tokens.add(JSON.stringify(info))
|
|
602
|
+
if (info.type) tokens.add(String(info.type))
|
|
603
|
+
if (info.kind) tokens.add(String(info.kind))
|
|
604
|
+
if (info.description) tokens.add(String(info.description))
|
|
605
|
+
if (Array.isArray(info.enumValues)) {
|
|
606
|
+
info.enumValues.forEach((value) => tokens.add(String(value)))
|
|
607
|
+
}
|
|
608
|
+
} else if (info !== null && info !== undefined) {
|
|
609
|
+
tokens.add(String(info))
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
return Array.from(tokens)
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function schemaEntryMatchesActiveFilter(sectionName, fullPath, info, engine, selectedIds) {
|
|
616
|
+
if (!engine.active) return true
|
|
617
|
+
|
|
618
|
+
let matched = false
|
|
619
|
+
if (selectedIds.includes(sectionName)) {
|
|
620
|
+
matched = schemaEntryTokens(fullPath, info).some((token) => engine.test(token))
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
if (!matched && selectedIds.includes('types')) {
|
|
624
|
+
const typeTokens = []
|
|
625
|
+
if (info && typeof info === 'object') {
|
|
626
|
+
if (info.type) typeTokens.push(String(info.type))
|
|
627
|
+
if (info.kind) typeTokens.push(String(info.kind))
|
|
628
|
+
if (Array.isArray(info.enumValues)) {
|
|
629
|
+
info.enumValues.forEach((value) => typeTokens.push(String(value)))
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if (typeMatchModeInput.value === 'exact' && !engine.regex) {
|
|
634
|
+
const needle = engine.caseSensitive ? engine.query : engine.query.toLowerCase()
|
|
635
|
+
const normalized = engine.caseSensitive
|
|
636
|
+
? typeTokens
|
|
637
|
+
: typeTokens.map((token) => token.toLowerCase())
|
|
638
|
+
matched = normalized.includes(needle)
|
|
639
|
+
} else {
|
|
640
|
+
matched = typeTokens.some((token) => engine.test(token))
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
return matched
|
|
645
|
+
}
|
|
646
|
+
|
|
560
647
|
function selectedFieldIds() {
|
|
561
648
|
return SEARCH_FIELDS.filter((field) => {
|
|
562
649
|
const input = document.getElementById(`field-${field.id}`)
|
|
@@ -568,10 +655,11 @@
|
|
|
568
655
|
if (!engine.active) return true
|
|
569
656
|
if (selectedIds.length === 0) return false
|
|
570
657
|
const schemaFlatByLeaf = state.payload?.schemaFlatByLeaf || {}
|
|
658
|
+
const payload = state.payload || {}
|
|
571
659
|
|
|
572
660
|
return SEARCH_FIELDS.some((field) => {
|
|
573
661
|
if (!selectedIds.includes(field.id)) return false
|
|
574
|
-
const tokens = toTokens(field.get(leaf, schemaFlatByLeaf))
|
|
662
|
+
const tokens = toTokens(field.get(leaf, schemaFlatByLeaf, payload))
|
|
575
663
|
if (field.id === 'types' && typeMatchModeInput.value === 'exact' && !engine.regex) {
|
|
576
664
|
const needle = engine.caseSensitive ? engine.query : engine.query.toLowerCase()
|
|
577
665
|
const normalized = engine.caseSensitive
|
|
@@ -629,6 +717,35 @@
|
|
|
629
717
|
return row
|
|
630
718
|
}
|
|
631
719
|
|
|
720
|
+
function sourceHref(source) {
|
|
721
|
+
if (!source || !source.file) return undefined
|
|
722
|
+
const normalizedPath = String(source.file).replace(/\\/g, '/')
|
|
723
|
+
const prefix = normalizedPath.startsWith('/') ? 'file://' : 'file:///'
|
|
724
|
+
return `${prefix}${encodeURI(normalizedPath)}`
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
function createSourceRow(key, source, engine) {
|
|
728
|
+
const box = el('div', 'kv')
|
|
729
|
+
box.appendChild(el('div', 'k', key))
|
|
730
|
+
const valueNode = el('div', 'v mono')
|
|
731
|
+
|
|
732
|
+
if (!source || !source.file) {
|
|
733
|
+
setHighlighted(valueNode, '—', engine)
|
|
734
|
+
box.appendChild(valueNode)
|
|
735
|
+
return box
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
const href = sourceHref(source)
|
|
739
|
+
const link = document.createElement('a')
|
|
740
|
+
link.href = href
|
|
741
|
+
link.target = '_blank'
|
|
742
|
+
link.rel = 'noopener noreferrer'
|
|
743
|
+
link.textContent = `${source.file}:${source.line}:${source.column}`
|
|
744
|
+
valueNode.appendChild(link)
|
|
745
|
+
box.appendChild(valueNode)
|
|
746
|
+
return box
|
|
747
|
+
}
|
|
748
|
+
|
|
632
749
|
function splitFlatSchemaBySection(flatSchema) {
|
|
633
750
|
const result = {
|
|
634
751
|
params: {},
|
|
@@ -737,17 +854,27 @@
|
|
|
737
854
|
return row
|
|
738
855
|
}
|
|
739
856
|
|
|
740
|
-
function renderSeparatedSchemas(flatSchema, engine) {
|
|
857
|
+
function renderSeparatedSchemas(flatSchema, engine, selectedIds) {
|
|
741
858
|
if (!flatSchema || typeof flatSchema !== 'object') return null
|
|
742
859
|
const section = el('div', 'section')
|
|
743
860
|
section.appendChild(el('h3', '', 'Schemas (separated by section)'))
|
|
744
861
|
|
|
745
862
|
const grouped = splitFlatSchemaBySection(flatSchema)
|
|
746
863
|
let hasAnySchemaEntries = false
|
|
864
|
+
const limitToMatchedRows = schemaRowsMatchOnlyInput.checked && engine.active
|
|
747
865
|
|
|
748
866
|
SCHEMA_SECTIONS.forEach((sectionName) => {
|
|
749
|
-
const
|
|
750
|
-
if (!
|
|
867
|
+
const rawEntries = grouped[sectionName]
|
|
868
|
+
if (!rawEntries || Object.keys(rawEntries).length === 0) return
|
|
869
|
+
|
|
870
|
+
const entries = limitToMatchedRows
|
|
871
|
+
? Object.fromEntries(
|
|
872
|
+
Object.entries(rawEntries).filter(([fullPath, info]) =>
|
|
873
|
+
schemaEntryMatchesActiveFilter(sectionName, fullPath, info, engine, selectedIds),
|
|
874
|
+
),
|
|
875
|
+
)
|
|
876
|
+
: rawEntries
|
|
877
|
+
if (Object.keys(entries).length === 0) return
|
|
751
878
|
|
|
752
879
|
hasAnySchemaEntries = true
|
|
753
880
|
const block = el('div', 'schema-block')
|
|
@@ -764,7 +891,7 @@
|
|
|
764
891
|
return hasAnySchemaEntries ? section : null
|
|
765
892
|
}
|
|
766
893
|
|
|
767
|
-
function renderLeaf(leaf, engine) {
|
|
894
|
+
function renderLeaf(leaf, engine, selectedIds) {
|
|
768
895
|
const details = el('details', 'leaf')
|
|
769
896
|
const summary = el('summary')
|
|
770
897
|
setHighlighted(summary, `${String(leaf.method || '').toUpperCase()} ${leaf.path || ''}`, engine)
|
|
@@ -823,7 +950,32 @@
|
|
|
823
950
|
content.appendChild(files)
|
|
824
951
|
}
|
|
825
952
|
|
|
826
|
-
const
|
|
953
|
+
const sourceByLeaf = state.payload?.sourceByLeaf || {}
|
|
954
|
+
const source = sourceByLeaf[leaf.key]
|
|
955
|
+
if (source) {
|
|
956
|
+
const sourceSection = el('div', 'section')
|
|
957
|
+
sourceSection.appendChild(el('h3', '', 'Source'))
|
|
958
|
+
sourceSection.appendChild(createSourceRow('definition', source.definition, engine))
|
|
959
|
+
|
|
960
|
+
const schemaSources = source.schemas || {}
|
|
961
|
+
const schemaEntries = Object.entries(schemaSources)
|
|
962
|
+
if (schemaEntries.length > 0) {
|
|
963
|
+
const schemaGrid = el('div', 'grid-2')
|
|
964
|
+
schemaEntries.forEach(([schemaName, schemaSource]) => {
|
|
965
|
+
const display = schemaSource?.sourceName
|
|
966
|
+
? `${schemaName}: ${schemaSource.sourceName}`
|
|
967
|
+
: schemaSource?.tag
|
|
968
|
+
? `${schemaName}: ${schemaSource.tag}`
|
|
969
|
+
: schemaName
|
|
970
|
+
schemaGrid.appendChild(createSourceRow(display, schemaSource, engine))
|
|
971
|
+
})
|
|
972
|
+
sourceSection.appendChild(schemaGrid)
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
content.appendChild(sourceSection)
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
const separatedSchemas = renderSeparatedSchemas(flatSchema, engine, selectedIds)
|
|
827
979
|
if (separatedSchemas) {
|
|
828
980
|
content.appendChild(separatedSchemas)
|
|
829
981
|
}
|
|
@@ -863,7 +1015,7 @@
|
|
|
863
1015
|
}
|
|
864
1016
|
|
|
865
1017
|
filtered.forEach((leaf) => {
|
|
866
|
-
resultsEl.appendChild(renderLeaf(leaf, engine))
|
|
1018
|
+
resultsEl.appendChild(renderLeaf(leaf, engine, selectedIds))
|
|
867
1019
|
})
|
|
868
1020
|
syncFilterStateToUrl()
|
|
869
1021
|
}
|
|
@@ -897,6 +1049,7 @@
|
|
|
897
1049
|
caseSensitiveInput.checked = false
|
|
898
1050
|
regexSearchInput.checked = false
|
|
899
1051
|
typeMatchModeInput.value = 'contains'
|
|
1052
|
+
schemaRowsMatchOnlyInput.checked = false
|
|
900
1053
|
setFieldSelection(new Set(SEARCH_FIELDS.map((field) => field.id)))
|
|
901
1054
|
}
|
|
902
1055
|
|
|
@@ -908,6 +1061,7 @@
|
|
|
908
1061
|
|
|
909
1062
|
if (searchValue) chips.push(`search: ${searchValue}`)
|
|
910
1063
|
if (typeMatchModeInput.value === 'exact') chips.push('type mode: exact')
|
|
1064
|
+
if (schemaRowsMatchOnlyInput.checked) chips.push('schema rows: matched only')
|
|
911
1065
|
if (caseSensitiveInput.checked) chips.push('case sensitive')
|
|
912
1066
|
if (regexSearchInput.checked) chips.push('regex')
|
|
913
1067
|
if (hasRegexError) chips.push('regex error')
|
|
@@ -935,6 +1089,7 @@
|
|
|
935
1089
|
caseSensitive: caseSensitiveInput.checked,
|
|
936
1090
|
regex: regexSearchInput.checked,
|
|
937
1091
|
typeMatchMode: typeMatchModeInput.value === 'exact' ? 'exact' : 'contains',
|
|
1092
|
+
schemaRowsMatchOnly: schemaRowsMatchOnlyInput.checked,
|
|
938
1093
|
selectedFields: selectedFieldIds(),
|
|
939
1094
|
}
|
|
940
1095
|
}
|
|
@@ -966,6 +1121,7 @@
|
|
|
966
1121
|
if (parsed.typeMatchMode === 'exact' || parsed.typeMatchMode === 'contains') {
|
|
967
1122
|
typeMatchModeInput.value = parsed.typeMatchMode
|
|
968
1123
|
}
|
|
1124
|
+
schemaRowsMatchOnlyInput.checked = Boolean(parsed.schemaRowsMatchOnly)
|
|
969
1125
|
|
|
970
1126
|
if (Array.isArray(parsed.selectedFields)) {
|
|
971
1127
|
const allowed = new Set(parsed.selectedFields)
|
|
@@ -1020,6 +1176,7 @@
|
|
|
1020
1176
|
caseSensitiveInput.addEventListener('change', renderResults)
|
|
1021
1177
|
regexSearchInput.addEventListener('change', renderResults)
|
|
1022
1178
|
typeMatchModeInput.addEventListener('change', renderResults)
|
|
1179
|
+
schemaRowsMatchOnlyInput.addEventListener('change', renderResults)
|
|
1023
1180
|
|
|
1024
1181
|
selectAllFieldsBtn.addEventListener('click', () =>
|
|
1025
1182
|
setFieldSelection(new Set(SEARCH_FIELDS.map((field) => field.id))),
|