Skip to content

Commit e579290

Browse files
committed
feat: finalized ui definition validation & updated schema & types
1 parent 87ac03f commit e579290

File tree

5 files changed

+99
-38
lines changed

5 files changed

+99
-38
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import z from 'zod';
2+
import { TUIElement, UIElementsSchemaWithChildren } from './elements';
3+
4+
export interface IUIDefinitionItem {
5+
elements: TUIElement[];
6+
}
7+
8+
const getValueAtPath = (obj: any, path: string) => {
9+
const pathParts = path.split('.').map(part => {
10+
// Convert numeric strings to numbers for array indices
11+
return /^\d+$/.test(part) ? Number(part) : part;
12+
});
13+
14+
let value = obj;
15+
for (const key of pathParts) {
16+
if (value === undefined || value === null) return undefined;
17+
value = value[key];
18+
}
19+
return value;
20+
};
21+
22+
export const assertUIDefinitionValid = (definition: IUIDefinitionItem[]) => {
23+
try {
24+
const result = z
25+
.array(
26+
z.object({
27+
elements: z.array(UIElementsSchemaWithChildren),
28+
}),
29+
)
30+
.parse(definition);
31+
32+
return result;
33+
} catch (error) {
34+
if (error instanceof z.ZodError) {
35+
console.error('\x1b[31mUI Definition Validation Errors:\x1b[0m');
36+
(error as z.ZodError).errors.forEach(err => {
37+
console.error(`\x1b[31mMessage: ${err.message}\x1b[0m`);
38+
console.log(
39+
'\x1b[31mInvalid value:\x1b[0m',
40+
'\x1b[32m' + getValueAtPath(definition, err.path.join('.')) + '\x1b[0m',
41+
);
42+
console.error(`\x1b[31mAt path: ${err.path.join('.')}\x1b[0m`);
43+
44+
if (err.code === 'invalid_union_discriminator') {
45+
console.error('\x1b[31mAllowed element types:\x1b[0m');
46+
err.options?.forEach(option => console.error(`\x1b[31m- ${String(option)}\x1b[0m`));
47+
}
48+
});
49+
}
50+
51+
throw new Error(`Validation failed: ${(error as z.ZodError).message}`);
52+
}
53+
};

packages/common/src/utils/collection-flow/schemas/elements/element.ts

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ import { ValidatorSchema } from '../validation/validator';
6262
import { CollectionFlowRuleSchema } from './common/rule';
6363
import { FieldSchema } from './common';
6464

65-
export const BaseUIElement = z.object({
65+
export let InitialUIElement = z.object({
6666
id: z.string(),
6767
valueDestination: z.string().optional(),
6868
defaultValue: z.any().optional(),
@@ -72,132 +72,139 @@ export const BaseUIElement = z.object({
7272
disable: z.array(CollectionFlowRuleSchema).optional(),
7373
});
7474

75-
export const BaseUIElementSchema = z.discriminatedUnion('element', [
75+
export let UIElementsSchema = z.discriminatedUnion('element', [
7676
// UI Elements start
77-
BaseUIElement.extend({
77+
InitialUIElement.extend({
7878
element: ColumnElementType,
7979
params: ColumnElementParamsSchema.optional(),
8080
}),
81-
BaseUIElement.extend({
81+
InitialUIElement.extend({
8282
element: RowElementType,
8383
params: RowElementParamsSchema.optional(),
8484
}),
85-
BaseUIElement.extend({
85+
InitialUIElement.extend({
8686
element: DescriptionElementType,
8787
params: DescriptionElementParamsSchema,
8888
}),
89-
BaseUIElement.extend({
89+
InitialUIElement.extend({
9090
element: H1ElementType,
9191
params: H1ElementParamsSchema,
9292
}),
93-
BaseUIElement.extend({
93+
InitialUIElement.extend({
9494
element: H3ElementType,
9595
params: H3ElementParamsSchema,
9696
}),
97-
BaseUIElement.extend({
97+
InitialUIElement.extend({
9898
element: H4ElementType,
9999
params: H4ElementParamsSchema,
100100
}),
101-
BaseUIElement.extend({
101+
InitialUIElement.extend({
102102
element: DividerElementType,
103103
}),
104104

105105
// UI Elements end
106106

107107
// Fields start
108-
BaseUIElement.extend({
108+
InitialUIElement.extend({
109109
element: AutocompleteFieldElementType,
110110
params: AutocompleteFieldParamsSchema,
111111
}),
112-
BaseUIElement.extend({
112+
InitialUIElement.extend({
113113
element: CheckboxFieldElementType,
114114
params: CheckboxFieldParamsSchema,
115115
}),
116-
BaseUIElement.extend({
116+
InitialUIElement.extend({
117117
element: CheckboxListElementType,
118118
params: CheckboxListParamsSchema,
119119
}),
120-
BaseUIElement.extend({
120+
InitialUIElement.extend({
121121
element: DateFieldElementType,
122122
params: DateFieldParamsSchema,
123123
}),
124-
BaseUIElement.extend({
124+
InitialUIElement.extend({
125125
element: DocumentFieldElementType,
126126
params: DocumentFieldParamsSchema,
127127
}),
128-
BaseUIElement.extend({
128+
InitialUIElement.extend({
129129
element: FieldListElementType,
130130
params: FieldListParamsSchema,
131131
}),
132-
BaseUIElement.extend({
132+
InitialUIElement.extend({
133133
element: EntityFieldGroupElementType,
134134
params: EntityFieldGroupParamsSchema,
135135
}),
136-
BaseUIElement.extend({
136+
InitialUIElement.extend({
137137
element: FileFieldElementType,
138138
params: FileFieldParamsSchema,
139139
}),
140-
BaseUIElement.extend({
140+
InitialUIElement.extend({
141141
element: MultiSelectFieldElementType,
142142
params: MultiSelectFieldParamsSchema,
143143
}),
144-
BaseUIElement.extend({
144+
InitialUIElement.extend({
145145
element: PhoneFieldElementType,
146146
params: PhoneFieldParamsSchema,
147147
}),
148-
BaseUIElement.extend({
148+
InitialUIElement.extend({
149149
element: RadioFieldElementType,
150150
params: RadioFieldParamsSchema,
151151
}),
152-
BaseUIElement.extend({
152+
InitialUIElement.extend({
153153
element: SelectFieldElementType,
154154
params: SelectFieldParamsSchema,
155155
}),
156-
BaseUIElement.extend({
156+
InitialUIElement.extend({
157157
element: TagsFieldElementType,
158158
params: TagsFieldParamsSchema,
159159
}),
160-
BaseUIElement.extend({
160+
InitialUIElement.extend({
161161
element: TextFieldElementType,
162162
params: TextFieldParamsSchema,
163163
}),
164-
BaseUIElement.extend({
164+
InitialUIElement.extend({
165165
element: IndustriesPickerFieldElementType,
166166
params: IndustriesPickerFieldParamsSchema,
167167
}),
168-
BaseUIElement.extend({
168+
InitialUIElement.extend({
169169
element: CountryPickerFieldElementType,
170170
params: CountryPickerFieldParamsSchema,
171171
}),
172-
BaseUIElement.extend({
172+
InitialUIElement.extend({
173173
element: LocalePickerFieldElementType,
174174
params: LocalePickerFieldParamsSchema,
175175
}),
176-
BaseUIElement.extend({
176+
InitialUIElement.extend({
177177
element: MCCPickerFieldElementType,
178178
params: MCCPickerFieldParamsSchema,
179179
}),
180-
BaseUIElement.extend({
180+
InitialUIElement.extend({
181181
element: NationalityPickerFieldElementType,
182182
params: NationalityPickerFieldParamsSchema,
183183
}),
184-
BaseUIElement.extend({
184+
InitialUIElement.extend({
185185
element: StatePickerFieldElementType,
186186
params: StatePickerFieldParamsSchema,
187187
}),
188-
BaseUIElement.extend({
188+
InitialUIElement.extend({
189189
element: TaxIdPickerFieldElementType,
190190
params: TaxIdPickerFieldParamsSchema,
191191
}),
192-
BaseUIElement.extend({
192+
InitialUIElement.extend({
193193
element: SubmitButtonElementType,
194194
params: SubmitParamsSchema,
195195
}),
196196
]);
197197

198-
export type TUIElements = z.infer<typeof BaseUIElementSchema>['element'];
198+
export const UIElementsSchemaWithChildren: z.ZodType<any> = z.intersection(
199+
UIElementsSchema,
200+
z.object({
201+
children: z.lazy(() => z.array(UIElementsSchemaWithChildren)).optional(),
202+
}),
203+
);
204+
205+
export type TUIElements = z.infer<typeof UIElementsSchema>['element'];
199206

200-
export type TUIElement = z.infer<typeof BaseUIElementSchema> & {
207+
export type TUIElement = z.infer<typeof UIElementsSchema> & {
201208
children?: TUIElement[];
202209
};
203210

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './elements';
22
export * from './config-schema';
33
export * from './validation';
4+
export * from './assert-ui-definition-valid';

pnpm-lock.yaml

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)