@@ -32,22 +32,29 @@ const httpsUrlSchema = v.pipe(
3232 v . url ( ) ,
3333 v . check ( ( value ) => new URL ( value ) . protocol === 'https:' , 'Expected HTTPS' ) ,
3434)
35- const referenceRendererSchema = v . picklist ( [
35+ const legacyReferenceRendererSchema = v . picklist ( [
3636 'observable-plot' ,
3737 'recharts' ,
3838 'echarts' ,
3939] )
40- const caseEntryPathSchema = v . pipe (
40+ const legacyCaseEntryPathSchema = v . pipe (
4141 v . string ( ) ,
4242 v . regex (
4343 / ^ b e n c h m a r k s \/ c o n f o r m a n c e \/ c a s e s \/ [ a - z 0 - 9 ] + (?: - [ a - z 0 - 9 ] + ) * \/ (?: t a n s t a c k | p l o t | r e c h a r t s | e c h a r t s ) \. t s $ / ,
44+ 'Invalid legacy catalog entry path' ,
45+ ) ,
46+ )
47+ const caseEntryPathSchema = v . pipe (
48+ v . string ( ) ,
49+ v . regex (
50+ / ^ b e n c h m a r k s \/ c o n f o r m a n c e \/ c a s e s \/ [ a - z 0 - 9 ] + (?: - [ a - z 0 - 9 ] + ) * \/ e x a m p l e \. t s x $ / ,
4451 'Invalid catalog entry path' ,
4552 ) ,
4653)
4754
4855// Deliberately use `object` here. The Charts benchmark owns geometry and
4956// interaction metadata; the site validates and retains only its UI contract.
50- const catalogCaseSchema = v . pipe (
57+ const legacyCatalogCaseSchema = v . pipe (
5158 v . object ( {
5259 schemaVersion : v . literal ( 1 ) ,
5360 order : nonNegativeIntegerSchema ,
@@ -67,10 +74,10 @@ const catalogCaseSchema = v.pipe(
6774 maintain : nonEmptyStringSchema ,
6875 } ) ,
6976 entries : v . strictObject ( {
70- tanstack : caseEntryPathSchema ,
77+ tanstack : legacyCaseEntryPathSchema ,
7178 reference : v . strictObject ( {
72- renderer : referenceRendererSchema ,
73- path : caseEntryPathSchema ,
79+ renderer : legacyReferenceRendererSchema ,
80+ path : legacyCaseEntryPathSchema ,
7481 } ) ,
7582 } ) ,
7683 } ) ,
@@ -83,7 +90,7 @@ const catalogCaseSchema = v.pipe(
8390 ( catalogCase ) =>
8491 catalogCase . entries . tanstack ===
8592 `benchmarks/conformance/cases/${ catalogCase . id } /tanstack.ts` ,
86- 'Catalog case TanStack entry must match its ID' ,
93+ 'Legacy catalog case TanStack entry must match its ID' ,
8794 ) ,
8895 v . check ( ( catalogCase ) => {
8996 const filename =
@@ -94,18 +101,64 @@ const catalogCaseSchema = v.pipe(
94101 catalogCase . entries . reference . path ===
95102 `benchmarks/conformance/cases/${ catalogCase . id } /${ filename } .ts`
96103 )
97- } , 'Catalog case reference entry must match its ID and renderer' ) ,
104+ } , 'Legacy catalog case reference entry must match its ID and renderer' ) ,
98105)
99106
100- const catalogIndexSchema = v . pipe (
101- v . strictObject ( {
107+ const catalogCaseSchema = v . pipe (
108+ v . object ( {
102109 schemaVersion : v . literal ( 1 ) ,
110+ order : nonNegativeIntegerSchema ,
111+ id : caseIdSchema ,
112+ collection : v . optional ( caseIdSchema ) ,
113+ title : nonEmptyStringSchema ,
114+ family : nonEmptyStringSchema ,
115+ intent : nonEmptyStringSchema ,
116+ support : v . picklist ( [ 'native' , 'composed' , 'gap' , 'deferred' ] ) ,
117+ features : v . array ( nonEmptyStringSchema ) ,
103118 source : v . strictObject ( {
104- repo : v . literal ( chartsCatalogIndexRepo ) ,
105- pathRoot : v . literal ( 'benchmarks/conformance/' ) ,
119+ title : nonEmptyStringSchema ,
120+ url : httpsUrlSchema ,
121+ } ) ,
122+ ai : v . strictObject ( {
123+ create : nonEmptyStringSchema ,
124+ maintain : nonEmptyStringSchema ,
125+ } ) ,
126+ entries : v . strictObject ( {
127+ example : caseEntryPathSchema ,
106128 } ) ,
107- cases : v . pipe ( v . array ( catalogCaseSchema ) , v . minLength ( 1 ) ) ,
108129 } ) ,
130+ v . check (
131+ ( catalogCase ) =>
132+ new Set ( catalogCase . features ) . size === catalogCase . features . length ,
133+ 'Catalog case features must be unique' ,
134+ ) ,
135+ v . check (
136+ ( catalogCase ) =>
137+ catalogCase . entries . example ===
138+ `benchmarks/conformance/cases/${ catalogCase . id } /example.tsx` ,
139+ 'Catalog case example entry must match its ID' ,
140+ ) ,
141+ )
142+
143+ const catalogIndexSchema = v . pipe (
144+ v . union ( [
145+ v . strictObject ( {
146+ schemaVersion : v . literal ( 1 ) ,
147+ source : v . strictObject ( {
148+ repo : v . literal ( chartsCatalogIndexRepo ) ,
149+ pathRoot : v . literal ( 'benchmarks/conformance/' ) ,
150+ } ) ,
151+ cases : v . pipe ( v . array ( legacyCatalogCaseSchema ) , v . minLength ( 1 ) ) ,
152+ } ) ,
153+ v . strictObject ( {
154+ schemaVersion : v . literal ( 2 ) ,
155+ source : v . strictObject ( {
156+ repo : v . literal ( chartsCatalogIndexRepo ) ,
157+ pathRoot : v . literal ( 'benchmarks/conformance/' ) ,
158+ } ) ,
159+ cases : v . pipe ( v . array ( catalogCaseSchema ) , v . minLength ( 1 ) ) ,
160+ } ) ,
161+ ] ) ,
109162 v . check ( ( index ) => {
110163 const ids = index . cases . map ( ( catalogCase ) => catalogCase . id )
111164 return new Set ( ids ) . size === ids . length
0 commit comments