@react-typed-forms/schemas 14.2.0 → 14.3.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.
@@ -0,0 +1,318 @@
1
+ import {
2
+ CompoundField,
3
+ FieldOption,
4
+ FieldType,
5
+ isCompoundField,
6
+ SchemaField,
7
+ SchemaMap,
8
+ } from "./schemaField";
9
+
10
+ export type AllowedSchema<T> = T extends string
11
+ ? SchemaField & {
12
+ type:
13
+ | FieldType.String
14
+ | FieldType.Date
15
+ | FieldType.DateTime
16
+ | FieldType.Time;
17
+ }
18
+ : T extends number
19
+ ? SchemaField & {
20
+ type: FieldType.Int | FieldType.Double;
21
+ }
22
+ : T extends boolean
23
+ ? SchemaField & {
24
+ type: FieldType.Bool;
25
+ }
26
+ : T extends Array<infer E>
27
+ ? AllowedSchema<E> & {
28
+ collection: true;
29
+ }
30
+ : T extends { [key: string]: any }
31
+ ? CompoundField & {
32
+ type: FieldType.Compound;
33
+ }
34
+ : SchemaField & { type: FieldType.Any };
35
+
36
+ type AllowedField<T, K> = (
37
+ name: string,
38
+ ) => (SchemaField & { type: K }) | AllowedSchema<T>;
39
+
40
+ export function buildSchema<T, Custom = "">(def: {
41
+ [K in keyof T]-?: AllowedField<T[K], Custom>;
42
+ }): SchemaField[] {
43
+ return Object.entries(def).map((x) =>
44
+ (x[1] as (n: string) => SchemaField)(x[0]),
45
+ );
46
+ }
47
+
48
+ export type FieldBuilder<T extends FieldType, K> = (
49
+ name: string,
50
+ ) => Omit<SchemaField, "type"> & { type: T } & K;
51
+
52
+ export function stringField(
53
+ displayName: string,
54
+ ): FieldBuilder<FieldType.String, {}>;
55
+
56
+ export function stringField<S extends Partial<SchemaField>>(
57
+ displayName: string,
58
+ options: S,
59
+ ): FieldBuilder<FieldType.String, S>;
60
+
61
+ export function stringField(displayName: string, options?: any) {
62
+ return makeScalarField({
63
+ type: FieldType.String,
64
+ displayName,
65
+ ...options,
66
+ });
67
+ }
68
+
69
+ export function stringOptionsField(
70
+ displayName: string,
71
+ ...options: FieldOption[]
72
+ ) {
73
+ return makeScalarField({
74
+ type: FieldType.String as const,
75
+ displayName,
76
+ options,
77
+ });
78
+ }
79
+
80
+ export function withScalarOptions<
81
+ S extends SchemaField,
82
+ S2 extends Partial<SchemaField>,
83
+ >(options: S2, v: (name: string) => S): (name: string) => S & S2 {
84
+ return (n) => ({ ...v(n), ...options });
85
+ }
86
+
87
+ export function makeScalarField<S extends Partial<SchemaField>>(
88
+ options: S,
89
+ ): (name: string) => SchemaField & S {
90
+ return (n) => ({ ...defaultScalarField(n, n), ...options });
91
+ }
92
+
93
+ export function makeCompoundField<S extends Partial<CompoundField>>(
94
+ options: S,
95
+ ): (name: string) => CompoundField & {
96
+ type: FieldType.Compound;
97
+ } & S {
98
+ return (n) => ({ ...defaultCompoundField(n, n, false), ...options });
99
+ }
100
+
101
+ export function intField(displayName: string): FieldBuilder<FieldType.Int, {}>;
102
+
103
+ export function intField<S extends Partial<SchemaField>>(
104
+ displayName: string,
105
+ options: S,
106
+ ): FieldBuilder<FieldType.Int, S>;
107
+
108
+ export function intField<S extends Partial<SchemaField>>(
109
+ displayName: string,
110
+ options?: S,
111
+ ) {
112
+ return makeScalarField({
113
+ type: FieldType.Int as const,
114
+ displayName,
115
+ ...(options as S),
116
+ });
117
+ }
118
+
119
+ export function doubleField(
120
+ displayName: string,
121
+ ): FieldBuilder<FieldType.Double, {}>;
122
+
123
+ export function doubleField<S extends Partial<SchemaField>>(
124
+ displayName: string,
125
+ options: S,
126
+ ): FieldBuilder<FieldType.Double, S>;
127
+
128
+ export function doubleField<S extends Partial<SchemaField>>(
129
+ displayName: string,
130
+ options?: S,
131
+ ) {
132
+ return makeScalarField({
133
+ type: FieldType.Double as const,
134
+ displayName,
135
+ ...(options as S),
136
+ });
137
+ }
138
+
139
+ export function dateField(
140
+ displayName: string,
141
+ ): FieldBuilder<FieldType.Date, {}>;
142
+
143
+ export function dateField<S extends Partial<SchemaField>>(
144
+ displayName: string,
145
+ options: S,
146
+ ): FieldBuilder<FieldType.Date, S>;
147
+
148
+ export function dateField<S extends Partial<SchemaField>>(
149
+ displayName: string,
150
+ options?: S,
151
+ ) {
152
+ return makeScalarField({
153
+ type: FieldType.Date as const,
154
+ displayName,
155
+ ...(options as S),
156
+ });
157
+ }
158
+
159
+ export function timeField<S extends Partial<SchemaField>>(
160
+ displayName: string,
161
+ options?: S,
162
+ ) {
163
+ return makeScalarField({
164
+ type: FieldType.Time as const,
165
+ displayName,
166
+ ...(options as S),
167
+ });
168
+ }
169
+
170
+ export function dateTimeField<S extends Partial<SchemaField>>(
171
+ displayName: string,
172
+ options?: S,
173
+ ) {
174
+ return makeScalarField({
175
+ type: FieldType.DateTime as const,
176
+ displayName,
177
+ ...(options as S),
178
+ });
179
+ }
180
+
181
+ export function boolField(
182
+ displayName: string,
183
+ ): FieldBuilder<FieldType.Bool, {}>;
184
+
185
+ export function boolField<S extends Partial<SchemaField>>(
186
+ displayName: string,
187
+ options: S,
188
+ ): FieldBuilder<FieldType.Bool, S>;
189
+
190
+ export function boolField(displayName: string, options?: any) {
191
+ return makeScalarField({
192
+ type: FieldType.Bool as const,
193
+ displayName,
194
+ ...options,
195
+ });
196
+ }
197
+
198
+ export function compoundField<
199
+ Other extends Partial<Omit<CompoundField, "type" | "schemaType">>,
200
+ >(
201
+ displayName: string,
202
+ fields: SchemaField[],
203
+ other?: Other,
204
+ ): (name: string) => CompoundField & {
205
+ collection: Other["collection"];
206
+ } {
207
+ return (field) =>
208
+ ({
209
+ ...defaultCompoundField(field, displayName, false),
210
+ ...other,
211
+ children: fields,
212
+ }) as any;
213
+ }
214
+
215
+ export function defaultScalarField(
216
+ field: string,
217
+ displayName: string,
218
+ ): Omit<SchemaField, "type"> & {
219
+ type: FieldType.String;
220
+ } {
221
+ return {
222
+ field,
223
+ displayName,
224
+ type: FieldType.String,
225
+ };
226
+ }
227
+
228
+ export function defaultCompoundField(
229
+ field: string,
230
+ displayName: string,
231
+ collection: boolean,
232
+ ): CompoundField & {
233
+ type: FieldType.Compound;
234
+ } {
235
+ return {
236
+ field,
237
+ displayName,
238
+ type: FieldType.Compound,
239
+ collection,
240
+ children: [],
241
+ };
242
+ }
243
+
244
+ export function mergeField(
245
+ field: SchemaField,
246
+ mergeInto: SchemaField[],
247
+ ): SchemaField[] {
248
+ const existing = mergeInto.find((x) => x.field === field.field);
249
+ if (existing) {
250
+ return mergeInto.map((x) =>
251
+ x !== existing
252
+ ? x
253
+ : {
254
+ ...x,
255
+ onlyForTypes: mergeTypes(x.onlyForTypes, field.onlyForTypes),
256
+ },
257
+ );
258
+ }
259
+ return [...mergeInto, field];
260
+
261
+ function mergeTypes(f?: string[] | null, s?: string[] | null) {
262
+ if (!f) return s;
263
+ if (!s) return f;
264
+ const extras = s.filter((x) => !f.includes(x));
265
+ return extras.length ? [...f, ...extras] : f;
266
+ }
267
+ }
268
+
269
+ export function mergeFields(
270
+ fields: SchemaField[],
271
+ name: string,
272
+ value: any,
273
+ newFields: SchemaField[],
274
+ ): SchemaField[] {
275
+ const withType = fields.map((x) =>
276
+ x.isTypeField ? addFieldOption(x, name, value) : x,
277
+ );
278
+ return newFields
279
+ .map((x) => ({ ...x, onlyForTypes: [value] }))
280
+ .reduce((af, x) => mergeField(x, af), withType);
281
+ }
282
+
283
+ export function addFieldOption(
284
+ typeField: SchemaField,
285
+ name: string,
286
+ value: any,
287
+ ): SchemaField {
288
+ const options = typeField.options ?? [];
289
+ if (options.some((x) => x.value === value)) return typeField;
290
+ return {
291
+ ...typeField,
292
+ options: [...options, { name, value }],
293
+ };
294
+ }
295
+
296
+ export function resolveSchemas<A extends SchemaMap>(schemaMap: A): A {
297
+ const out: SchemaMap = {};
298
+ function resolveSchemaType(type: string) {
299
+ if (type in out) {
300
+ return out[type];
301
+ }
302
+ const resolvedFields: SchemaField[] = [];
303
+ out[type] = resolvedFields;
304
+ schemaMap[type].forEach((x) => {
305
+ if (isCompoundField(x) && x.schemaRef) {
306
+ resolvedFields.push({
307
+ ...x,
308
+ children: resolveSchemaType(x.schemaRef),
309
+ } as CompoundField);
310
+ } else {
311
+ resolvedFields.push(x);
312
+ }
313
+ });
314
+ return resolvedFields;
315
+ }
316
+ Object.keys(schemaMap).forEach(resolveSchemaType);
317
+ return out as A;
318
+ }