@redocly/theme 0.33.3 → 0.35.0

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/src/config.ts CHANGED
@@ -1,752 +1,33 @@
1
- import type { FromSchema } from 'json-schema-to-ts';
2
- import type { MenuStyle, ResolvedNavLinkItem } from './types/portal';
3
- import type { REDOCLY_TEAMS_RBAC } from './types/portal/src/shared/constants';
4
-
5
- const logoConfigSchema = {
6
- type: 'object',
7
- properties: {
8
- image: { type: 'string' },
9
- srcSet: { type: 'string' },
10
- altText: { type: 'string' },
11
- link: { type: 'string' },
12
- favicon: { type: 'string' },
13
- },
14
- additionalProperties: false,
15
- } as const;
16
-
17
- const hideConfigSchema = {
18
- type: 'object',
19
- properties: {
20
- hide: { type: 'boolean' },
21
- },
22
- additionalProperties: false,
23
- } as const;
24
-
25
- const scriptConfigSchema = {
26
- type: 'object',
27
- properties: {
28
- src: { type: 'string' },
29
- async: { type: 'boolean' },
30
- crossorigin: { type: 'string' },
31
- defer: { type: 'boolean' },
32
- fetchpriority: { type: 'string' },
33
- integrity: { type: 'string' },
34
- module: { type: 'boolean' },
35
- nomodule: { type: 'boolean' },
36
- nonce: { type: 'string' },
37
- referrerpolicy: { type: 'string' },
38
- type: { type: 'string' },
39
- },
40
- required: ['src'],
41
- additionalProperties: true,
42
- } as const;
43
-
44
- const linksConfigSchema = {
45
- type: 'object',
46
- properties: {
47
- href: { type: 'string' },
48
- as: { type: 'string' },
49
- crossorigin: { type: 'string' },
50
- fetchpriority: { type: 'string' },
51
- hreflang: { type: 'string' },
52
- imagesizes: { type: 'string' },
53
- imagesrcset: { type: 'string' },
54
- integrity: { type: 'string' },
55
- media: { type: 'string' },
56
- prefetch: { type: 'string' },
57
- referrerpolicy: { type: 'string' },
58
- rel: { type: 'string' },
59
- sizes: { type: 'string' },
60
- title: { type: 'string' },
61
- type: { type: 'string' },
62
- },
63
- required: ['href'],
64
- additionalProperties: true,
65
- } as const;
66
-
67
- const markdownConfigSchema = {
68
- type: 'object',
69
- properties: {
70
- frontMatterKeysToResolve: {
71
- type: 'array',
72
- items: { type: 'string' },
73
- default: ['image', 'links'],
74
- },
75
- partialsFolders: {
76
- type: 'array',
77
- items: { type: 'string' },
78
- default: ['_partials'],
79
- },
80
- lastUpdatedBlock: {
81
- type: 'object',
82
- properties: {
83
- format: {
84
- type: 'string',
85
- enum: ['timeago', 'iso', 'long', 'short'],
86
- default: 'timeago',
87
- },
88
- locale: { type: 'string' },
89
- ...hideConfigSchema.properties,
90
- },
91
- additionalProperties: false,
92
- default: {},
93
- },
94
- toc: {
95
- type: 'object',
96
- properties: {
97
- header: { type: 'string', default: 'On this page' },
98
- depth: { type: 'integer', default: 3, minimum: 1 },
99
- ...hideConfigSchema.properties,
100
- },
101
- additionalProperties: false,
102
- default: {},
103
- },
104
- editPage: {
105
- type: 'object',
106
- properties: {
107
- baseUrl: { type: 'string' },
108
- ...hideConfigSchema.properties,
109
- },
110
- additionalProperties: false,
111
- default: {},
112
- },
113
- },
114
- additionalProperties: false,
115
- default: {},
116
- } as const;
117
-
118
- const amplitudeAnalyticsConfigSchema = {
119
- type: 'object',
120
- properties: {
121
- includeInDevelopment: { type: 'boolean' },
122
- apiKey: { type: 'string' },
123
- head: { type: 'boolean' },
124
- respectDNT: { type: 'boolean' },
125
- exclude: { type: 'array', items: { type: 'string' } },
126
- outboundClickEventName: { type: 'string' },
127
- pageViewEventName: { type: 'string' },
128
- amplitudeConfig: { type: 'object', additionalProperties: true },
129
- },
130
- additionalProperties: false,
131
- required: ['apiKey'],
132
- } as const;
133
-
134
- const fullstoryAnalyticsConfigSchema = {
135
- type: 'object',
136
- properties: {
137
- includeInDevelopment: { type: 'boolean' },
138
- orgId: { type: 'string' },
139
- },
140
- additionalProperties: false,
141
- required: ['orgId'],
142
- } as const;
143
-
144
- const heapAnalyticsConfigSchema = {
145
- type: 'object',
146
- properties: {
147
- includeInDevelopment: { type: 'boolean' },
148
- appId: { type: 'string' },
149
- },
150
- additionalProperties: false,
151
- required: ['appId'],
152
- } as const;
153
-
154
- const rudderstackAnalyticsConfigSchema = {
155
- type: 'object',
156
- properties: {
157
- includeInDevelopment: { type: 'boolean' },
158
- writeKey: { type: 'string', minLength: 10 },
159
- trackPage: { type: 'boolean' },
160
- dataPlaneUrl: { type: 'string' },
161
- controlPlaneUrl: { type: 'string' },
162
- sdkUrl: { type: 'string' },
163
- loadOptions: { type: 'object', additionalProperties: true },
164
- },
165
- additionalProperties: false,
166
- required: ['writeKey'],
167
- } as const;
168
-
169
- const segmentAnalyticsConfigSchema = {
170
- type: 'object',
171
- properties: {
172
- includeInDevelopment: { type: 'boolean' },
173
- writeKey: { type: 'string', minLength: 10 },
174
- trackPage: { type: 'boolean' },
175
- includeTitleInPageCall: { type: 'boolean' },
176
- host: { type: 'string' },
177
- },
178
- additionalProperties: false,
179
- required: ['writeKey'],
180
- } as const;
181
-
182
- const gtmAnalyticsConfigSchema = {
183
- type: 'object',
184
- properties: {
185
- includeInDevelopment: { type: 'boolean' },
186
- trackingId: { type: 'string' },
187
- gtmAuth: { type: 'string' },
188
- gtmPreview: { type: 'string' },
189
- defaultDataLayer: {},
190
- dataLayerName: { type: 'string' },
191
- enableWebVitalsTracking: { type: 'boolean' },
192
- selfHostedOrigin: { type: 'string' },
193
- pageViewEventName: { type: 'string' },
194
- },
195
- additionalProperties: false,
196
- required: ['trackingId'],
197
- } as const;
198
-
199
- const googleAnalyticsConfigSchema = {
200
- type: 'object',
201
- properties: {
202
- includeInDevelopment: { type: 'boolean' },
203
- trackingId: { type: 'string' },
204
-
205
- conversionId: { type: 'string' },
206
- floodlightId: { type: 'string' },
207
-
208
- head: { type: 'boolean' },
209
- respectDNT: { type: 'boolean' },
210
- exclude: { type: 'array', items: { type: 'string' } },
211
-
212
- optimizeId: { type: 'string' },
213
- anonymizeIp: { type: 'boolean' },
214
- cookieExpires: { type: 'number' },
215
- },
216
- additionalProperties: false,
217
- required: ['trackingId'],
218
- } as const;
219
-
220
- const adobeAnalyticsConfigSchema = {
221
- type: 'object',
222
- properties: {
223
- includeInDevelopment: { type: 'boolean' },
224
- scriptUrl: { type: 'string' },
225
- pageViewEventName: { type: 'string' },
226
- },
227
- additionalProperties: false,
228
- required: ['scriptUrl'],
229
- } as const;
230
-
231
- const navItemSchema = {
232
- type: 'object',
233
- properties: {
234
- page: { type: 'string' },
235
- directory: { type: 'string' },
236
- disconnect: { type: 'boolean', default: false },
237
- group: { type: 'string' },
238
- label: { type: 'string' },
239
- separator: { type: 'string' },
240
- separatorLine: { type: 'boolean' },
241
- linePosition: {
242
- type: 'string',
243
- enum: ['top', 'bottom'],
244
- default: 'top',
245
- },
246
- version: { type: 'string' },
247
- menuStyle: { type: 'string', enum: ['drilldown' as MenuStyle] },
248
- expanded: { type: 'string', const: 'always' },
249
- selectFirstItemOnExpand: { type: 'boolean' },
250
- flatten: { type: 'boolean' },
251
- linkedSidebars: {
252
- type: 'array',
253
- items: { type: 'string' },
254
- },
255
- },
256
- } as const;
257
-
258
- const navItemsSchema = {
259
- type: 'array',
260
- items: {
261
- ...navItemSchema,
262
- properties: {
263
- ...navItemSchema.properties,
264
- items: { type: 'array', items: navItemSchema },
265
- },
266
- },
267
- } as const;
268
-
269
- const productConfigSchema = {
270
- type: 'object',
271
- properties: {
272
- name: { type: 'string' },
273
- icon: { type: 'string' },
274
- folder: { type: 'string' },
275
- },
276
- additionalProperties: false,
277
- required: ['name', 'folder'],
278
- } as const;
279
-
280
- const suggestedPageSchema = {
281
- type: 'object',
282
- properties: {
283
- page: { type: 'string' },
284
- label: { type: 'string' },
285
- labelTranslationKey: { type: 'string' },
286
- },
287
- required: ['page'],
288
- } as const;
289
-
290
- const catalogFilterSchema = {
291
- type: 'object',
292
- additionalProperties: false,
293
- required: ['title', 'property'],
294
- properties: {
295
- type: { type: 'string', enum: ['select', 'checkboxes', 'date-range'] },
296
- title: { type: 'string' },
297
- titleTranslationKey: { type: 'string' },
298
- property: { type: 'string' },
299
- parentFilter: { type: 'string' },
300
- valuesMapping: { type: 'object', additionalProperties: { type: 'string' } },
301
- missingCategoryName: { type: 'string' },
302
- missingCategoryNameTranslationKey: { type: 'string' },
303
- options: { type: 'array', items: { type: 'string' } },
304
- },
305
- } as const;
306
-
307
- const scorecardConfigSchema = {
308
- type: 'object',
309
- additionalProperties: true,
310
- required: [],
311
- properties: {
312
- ignoreNonCompliant: { type: 'boolean', default: false },
313
- teamMetadataProperty: {
314
- type: 'object',
315
- properties: {
316
- property: { type: 'string' },
317
- label: { type: 'string' },
318
- default: { type: 'string' },
319
- },
320
- },
321
- levels: {
322
- type: 'array',
323
- items: {
324
- type: 'object',
325
- required: ['name'],
326
- properties: {
327
- name: { type: 'string' },
328
- color: { type: 'string' },
329
- extends: { type: 'array', items: { type: 'string' } },
330
- rules: {
331
- type: 'object',
332
- additionalProperties: {
333
- type: ['object', 'string'],
334
- },
335
- },
336
- },
337
- additionalProperties: false,
338
- },
339
- },
340
- targets: {
341
- type: 'array',
342
- items: {
343
- type: 'object',
344
- required: ['where'],
345
- properties: {
346
- minimumLevel: { type: 'string' },
347
- where: {
348
- type: 'object',
349
- required: ['metadata'],
350
- properties: {
351
- metadata: { type: 'object', additionalProperties: { type: 'string' } },
352
- },
353
- additionalProperties: false,
354
- },
355
- },
356
- additionalProperties: false,
357
- },
358
- },
359
- },
360
- } as const;
361
-
362
- const catalogSchema = {
363
- type: 'object',
364
- additionalProperties: true,
365
- required: ['slug', 'items'],
366
- properties: {
367
- slug: { type: 'string' },
368
- filters: { type: 'array', items: catalogFilterSchema },
369
- groupByFirstFilter: { type: 'boolean' },
370
- filterValuesCasing: {
371
- type: 'string',
372
- enum: ['sentence', 'original', 'lowercase', 'uppercase'],
373
- },
374
- items: navItemsSchema,
375
- requiredPermission: { type: 'string' },
376
- separateVersions: { type: 'boolean' },
377
- title: { type: 'string' },
378
- titleTranslationKey: { type: 'string' },
379
- description: { type: 'string' },
380
- descriptionTranslationKey: { type: 'string' },
381
- },
382
- } as const;
383
-
384
- const catalogsConfigSchema = {
385
- type: 'object',
386
- patternProperties: {
387
- '.*': catalogSchema,
388
- },
389
- } as const;
390
-
391
- export const themeConfigSchema = {
392
- type: 'object',
393
- properties: {
394
- imports: {
395
- type: 'array',
396
- items: { type: 'string' },
397
- default: [],
398
- },
399
- logo: logoConfigSchema,
400
- navbar: {
401
- type: 'object',
402
- properties: {
403
- items: navItemsSchema,
404
- ...hideConfigSchema.properties,
405
- },
406
- additionalProperties: false,
407
- },
408
- products: {
409
- type: 'object',
410
- additionalProperties: productConfigSchema,
411
- },
412
- footer: {
413
- type: 'object',
414
- properties: {
415
- items: navItemsSchema,
416
- copyrightText: { type: 'string' },
417
- logo: hideConfigSchema,
418
- ...hideConfigSchema.properties,
419
- },
420
- additionalProperties: false,
421
- },
422
- sidebar: {
423
- type: 'object',
424
- properties: {
425
- separatorLine: { type: 'boolean' },
426
- linePosition: {
427
- type: 'string',
428
- enum: ['top', 'bottom'],
429
- default: 'bottom',
430
- },
431
- ...hideConfigSchema.properties,
432
- },
433
- additionalProperties: false,
434
- },
435
- scripts: {
436
- type: 'object',
437
- properties: {
438
- head: { type: 'array', items: scriptConfigSchema },
439
- body: { type: 'array', items: scriptConfigSchema },
440
- },
441
- additionalProperties: false,
442
- },
443
- links: { type: 'array', items: linksConfigSchema },
444
- feedback: {
445
- type: 'object',
446
- properties: {
447
- hide: {
448
- type: 'boolean',
449
- default: false,
450
- },
451
- type: {
452
- type: 'string',
453
- enum: ['rating', 'sentiment', 'comment', 'reasons', 'mood', 'scale'],
454
- default: 'sentiment',
455
- },
456
- settings: {
457
- type: 'object',
458
- properties: {
459
- label: { type: 'string' },
460
- submitText: { type: 'string' },
461
- buttonText: { type: 'string' },
462
- component: {
463
- type: 'string',
464
- enum: ['radio', 'checkbox'],
465
- default: 'checkbox',
466
- },
467
- items: { type: 'array', items: { type: 'string' }, minItems: 1 },
468
- leftScaleLabel: { type: 'string' },
469
- rightScaleLabel: { type: 'string' },
470
- reasons: {
471
- type: 'object',
472
- properties: {
473
- hide: {
474
- type: 'boolean',
475
- default: false,
476
- },
477
- component: {
478
- type: 'string',
479
- enum: ['radio', 'checkbox'],
480
- default: 'checkbox',
481
- },
482
- label: { type: 'string' },
483
- items: { type: 'array', items: { type: 'string' } },
484
- },
485
- additionalProperties: false,
486
- },
487
- comment: {
488
- type: 'object',
489
- properties: {
490
- hide: {
491
- type: 'boolean',
492
- default: false,
493
- },
494
- label: { type: 'string' },
495
- likeLabel: { type: 'string' },
496
- dislikeLabel: { type: 'string' },
497
- satisfiedLabel: { type: 'string' },
498
- neutralLabel: { type: 'string' },
499
- dissatisfiedLabel: { type: 'string' },
500
- },
501
- additionalProperties: false,
502
- },
503
- },
504
- additionalProperties: false,
505
- ...hideConfigSchema.properties,
506
- },
507
- },
508
- additionalProperties: false,
509
- default: {},
510
- },
511
- search: {
512
- type: 'object',
513
- properties: {
514
- placement: {
515
- type: 'string',
516
- default: 'navbar',
517
- },
518
- shortcuts: {
519
- type: 'array',
520
- items: { type: 'string' },
521
- default: ['/'],
522
- },
523
- suggestedPages: {
524
- type: 'array',
525
- items: suggestedPageSchema,
526
- },
527
- ...hideConfigSchema.properties,
528
- },
529
- additionalProperties: false,
530
- default: {},
531
- },
532
- colorMode: {
533
- type: 'object',
534
- properties: {
535
- ignoreDetection: { type: 'boolean' },
536
- modes: {
537
- type: 'array',
538
- items: { type: 'string' },
539
- default: ['light', 'dark'],
540
- },
541
- ...hideConfigSchema.properties,
542
- },
543
- additionalProperties: false,
544
- default: {},
545
- },
546
- navigation: {
547
- type: 'object',
548
- properties: {
549
- nextButton: {
550
- type: 'object',
551
- properties: {
552
- text: { type: 'string', default: 'Next to {{label}}' },
553
- ...hideConfigSchema.properties,
554
- },
555
- additionalProperties: false,
556
- default: {},
557
- },
558
- previousButton: {
559
- type: 'object',
560
- properties: {
561
- text: { type: 'string', default: 'Back to {{label}}' },
562
- ...hideConfigSchema.properties,
563
- },
564
- additionalProperties: false,
565
- default: {},
566
- },
567
- },
568
- additionalProperties: false,
569
- default: {},
570
- },
571
- codeSnippet: {
572
- type: 'object',
573
- properties: {
574
- elementFormat: { type: 'string', default: 'icon' },
575
- copy: {
576
- type: 'object',
577
- properties: {
578
- ...hideConfigSchema.properties,
579
- },
580
- additionalProperties: false,
581
- default: { hide: false },
582
- },
583
- report: {
584
- type: 'object',
585
- properties: {
586
- tooltipText: { type: 'string' },
587
- buttonText: { type: 'string' },
588
- label: { type: 'string' },
589
- ...hideConfigSchema.properties,
590
- },
591
- additionalProperties: false,
592
- default: { hide: false },
593
- },
594
- expand: {
595
- type: 'object',
596
- properties: {
597
- ...hideConfigSchema.properties,
598
- },
599
- additionalProperties: false,
600
- default: { hide: false },
601
- },
602
- collapse: {
603
- type: 'object',
604
- properties: {
605
- ...hideConfigSchema.properties,
606
- },
607
- additionalProperties: false,
608
- default: { hide: false },
609
- },
610
- },
611
- additionalProperties: false,
612
- default: {},
613
- },
614
- markdown: markdownConfigSchema,
615
- openapi: { type: 'object', additionalProperties: true },
616
- graphql: { type: 'object', additionalProperties: true },
617
- analytics: {
618
- type: 'object',
619
- properties: {
620
- adobe: adobeAnalyticsConfigSchema,
621
- amplitude: amplitudeAnalyticsConfigSchema,
622
- fullstory: fullstoryAnalyticsConfigSchema,
623
- heap: heapAnalyticsConfigSchema,
624
- rudderstack: rudderstackAnalyticsConfigSchema,
625
- segment: segmentAnalyticsConfigSchema,
626
- gtm: gtmAnalyticsConfigSchema,
627
- ga: googleAnalyticsConfigSchema,
628
- },
629
- },
630
- userProfile: {
631
- type: 'object',
632
- properties: {
633
- loginLabel: { type: 'string', default: 'Login' },
634
- logoutLabel: { type: 'string', default: 'Logout' },
635
- menu: {
636
- type: 'array',
637
- items: {
638
- type: 'object',
639
- properties: {
640
- label: { type: 'string' },
641
- external: { type: 'boolean' },
642
- link: { type: 'string' },
643
- separatorLine: { type: 'boolean' },
644
- },
645
- additionalProperties: true,
646
- },
647
- default: [],
648
- },
649
- ...hideConfigSchema.properties,
650
- },
651
- additionalProperties: false,
652
- default: {},
653
- },
654
- versionPicker: {
655
- type: 'object',
656
- properties: {
657
- hide: { type: 'boolean' },
658
- showForUnversioned: {
659
- type: 'boolean',
660
- },
661
- },
662
- },
663
- breadcrumbs: {
664
- type: 'object',
665
- properties: {
666
- hide: { type: 'boolean' },
667
- prefixItems: {
668
- type: 'array',
669
- items: {
670
- type: 'object',
671
- properties: {
672
- label: { type: 'string' },
673
- labelTranslationKey: { type: 'string' },
674
- page: { type: 'string' },
675
- },
676
- additionalProperties: false,
677
- default: {},
678
- },
679
- },
680
- },
681
- additionalProperties: false,
682
- default: {},
683
- },
684
- catalog: catalogsConfigSchema,
685
- scorecard: scorecardConfigSchema,
686
- },
687
- additionalProperties: true,
688
- default: {},
689
- } as const;
690
-
691
- export const productThemeOverrideSchema = {
692
- type: 'object',
693
- properties: {
694
- logo: themeConfigSchema.properties.logo,
695
- navbar: themeConfigSchema.properties.navbar,
696
- footer: themeConfigSchema.properties.footer,
697
- sidebar: themeConfigSchema.properties.sidebar,
698
- search: themeConfigSchema.properties.search,
699
- codeSnippet: themeConfigSchema.properties.codeSnippet,
700
- breadcrumbs: themeConfigSchema.properties.breadcrumbs,
701
- },
702
- additionalProperties: true,
703
- default: {},
704
- } as const;
705
-
706
- export type ThemeConfig = FromSchema<typeof themeConfigSchema>;
707
-
708
- export type ThemeUIConfig = ThemeConfig & {
709
- auth?: {
710
- // used by portal dev login emulator
711
- idpsInfo?: {
712
- idpId: string;
713
- type: string; // AuthProviderType
714
- title: string | undefined;
715
- }[];
716
- devLogin?: boolean;
717
- loginUrls?: Record<string, string>;
718
- };
719
- search?: {
720
- shortcuts?: string[];
721
- suggestedPages?: any[];
722
- };
723
- breadcrumbs?: {
724
- prefixItems?: ResolvedNavLinkItem[];
725
- };
726
- products?: {
727
- [key: string]: ProductUiConfig;
728
- };
729
- };
730
-
731
- export type ProductConfig = FromSchema<typeof productConfigSchema>;
732
- export type ProductThemeOverrideConfig = Pick<
1
+ import type {
2
+ ThemeConfig,
3
+ ProductConfig,
4
+ CatalogFilterConfig,
5
+ CatalogConfig,
6
+ AmplitudeAnalyticsConfig,
7
+ GoogleAnalyticsConfig,
8
+ SegmentAnalyticsConfig,
9
+ RudderstackAnalyticsConfig,
10
+ GtmAnalyticsConfig,
11
+ ScorecardConfig,
12
+ ProductGoogleAnalyticsConfig,
13
+ ProductThemeOverrideConfig,
14
+ ThemeUIConfig,
15
+ ProductUiConfig,
16
+ } from '@redocly/config';
17
+
18
+ export type {
19
+ ThemeConfig,
20
+ ProductConfig,
21
+ CatalogFilterConfig,
22
+ CatalogConfig,
23
+ AmplitudeAnalyticsConfig,
24
+ GoogleAnalyticsConfig,
25
+ SegmentAnalyticsConfig,
26
+ RudderstackAnalyticsConfig,
27
+ GtmAnalyticsConfig,
28
+ ScorecardConfig,
29
+ ProductGoogleAnalyticsConfig,
30
+ ProductThemeOverrideConfig,
733
31
  ThemeUIConfig,
734
- 'logo' | 'navbar' | 'footer' | 'sidebar' | 'search' | 'codeSnippet' | 'breadcrumbs'
735
- >;
736
- export type ProductUiConfig = ProductConfig & {
737
- slug: string;
738
- link: string;
739
- [REDOCLY_TEAMS_RBAC]?: { [key: string]: string };
740
- themeOverride?: ProductThemeOverrideConfig;
32
+ ProductUiConfig,
741
33
  };
742
-
743
- export type MarkdownConfig = FromSchema<typeof markdownConfigSchema>;
744
-
745
- export type AmplitudeAnalyticsConfig = FromSchema<typeof amplitudeAnalyticsConfigSchema>;
746
- export type RudderstackAnalyticsConfig = FromSchema<typeof rudderstackAnalyticsConfigSchema>;
747
- export type SegmentAnalyticsConfig = FromSchema<typeof segmentAnalyticsConfigSchema>;
748
- export type GtmAnalyticsConfig = FromSchema<typeof gtmAnalyticsConfigSchema>;
749
- export type GoogleAnalyticsConfig = FromSchema<typeof googleAnalyticsConfigSchema>;
750
- export type CatalogConfig = FromSchema<typeof catalogSchema>;
751
- export type CatalogFilterConfig = FromSchema<typeof catalogFilterSchema>;
752
- export type ScorecardConfig = FromSchema<typeof scorecardConfigSchema>;