@rjsf/utils 5.13.0 → 5.13.1

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.
Files changed (35) hide show
  1. package/dist/index.js +243 -125
  2. package/dist/index.js.map +4 -4
  3. package/dist/utils.esm.js +243 -125
  4. package/dist/utils.esm.js.map +4 -4
  5. package/dist/utils.umd.js +223 -111
  6. package/lib/getOptionMatchingSimpleDiscriminator.d.ts +12 -0
  7. package/lib/getOptionMatchingSimpleDiscriminator.js +36 -0
  8. package/lib/getOptionMatchingSimpleDiscriminator.js.map +1 -0
  9. package/lib/getSchemaType.js +7 -2
  10. package/lib/getSchemaType.js.map +1 -1
  11. package/lib/index.d.ts +2 -1
  12. package/lib/index.js +2 -1
  13. package/lib/index.js.map +1 -1
  14. package/lib/parser/schemaParser.js +3 -2
  15. package/lib/parser/schemaParser.js.map +1 -1
  16. package/lib/schema/getClosestMatchingOption.js +7 -1
  17. package/lib/schema/getClosestMatchingOption.js.map +1 -1
  18. package/lib/schema/getDefaultFormState.js +9 -12
  19. package/lib/schema/getDefaultFormState.js.map +1 -1
  20. package/lib/schema/getMatchingOption.js +6 -0
  21. package/lib/schema/getMatchingOption.js.map +1 -1
  22. package/lib/schema/retrieveSchema.d.ts +16 -14
  23. package/lib/schema/retrieveSchema.js +57 -43
  24. package/lib/schema/retrieveSchema.js.map +1 -1
  25. package/lib/types.d.ts +1 -1
  26. package/package.json +15 -15
  27. package/src/getOptionMatchingSimpleDiscriminator.ts +46 -0
  28. package/src/getSchemaType.ts +6 -2
  29. package/src/index.ts +2 -0
  30. package/src/parser/schemaParser.ts +3 -2
  31. package/src/schema/getClosestMatchingOption.ts +9 -1
  32. package/src/schema/getDefaultFormState.ts +9 -12
  33. package/src/schema/getMatchingOption.ts +8 -0
  34. package/src/schema/retrieveSchema.ts +145 -39
  35. package/src/types.ts +1 -1
@@ -1,4 +1,5 @@
1
1
  import get from 'lodash/get';
2
+ import isEqual from 'lodash/isEqual';
2
3
  import set from 'lodash/set';
3
4
  import times from 'lodash/times';
4
5
  import transform from 'lodash/transform';
@@ -59,6 +60,7 @@ export function resolveCondition<T = any, S extends StrictRJSFSchema = RJSFSchem
59
60
  schema: S,
60
61
  rootSchema: S,
61
62
  expandAllBranches: boolean,
63
+ recurseList: string[],
62
64
  formData?: T
63
65
  ): S[] {
64
66
  const { if: expression, then, else: otherwise, ...resolvedSchemaLessConditional } = schema;
@@ -69,19 +71,26 @@ export function resolveCondition<T = any, S extends StrictRJSFSchema = RJSFSchem
69
71
  if (expandAllBranches) {
70
72
  if (then && typeof then !== 'boolean') {
71
73
  schemas = schemas.concat(
72
- retrieveSchemaInternal<T, S, F>(validator, then as S, rootSchema, formData, expandAllBranches)
74
+ retrieveSchemaInternal<T, S, F>(validator, then as S, rootSchema, formData, expandAllBranches, recurseList)
73
75
  );
74
76
  }
75
77
  if (otherwise && typeof otherwise !== 'boolean') {
76
78
  schemas = schemas.concat(
77
- retrieveSchemaInternal<T, S, F>(validator, otherwise as S, rootSchema, formData, expandAllBranches)
79
+ retrieveSchemaInternal<T, S, F>(validator, otherwise as S, rootSchema, formData, expandAllBranches, recurseList)
78
80
  );
79
81
  }
80
82
  } else {
81
83
  const conditionalSchema = conditionValue ? then : otherwise;
82
84
  if (conditionalSchema && typeof conditionalSchema !== 'boolean') {
83
85
  schemas = schemas.concat(
84
- retrieveSchemaInternal<T, S, F>(validator, conditionalSchema as S, rootSchema, formData, expandAllBranches)
86
+ retrieveSchemaInternal<T, S, F>(
87
+ validator,
88
+ conditionalSchema as S,
89
+ rootSchema,
90
+ formData,
91
+ expandAllBranches,
92
+ recurseList
93
+ )
85
94
  );
86
95
  }
87
96
  }
@@ -89,7 +98,7 @@ export function resolveCondition<T = any, S extends StrictRJSFSchema = RJSFSchem
89
98
  resolvedSchemas = schemas.map((s) => mergeSchemas(resolvedSchemaLessConditional, s) as S);
90
99
  }
91
100
  return resolvedSchemas.flatMap((s) =>
92
- retrieveSchemaInternal<T, S, F>(validator, s, rootSchema, formData, expandAllBranches)
101
+ retrieveSchemaInternal<T, S, F>(validator, s, rootSchema, formData, expandAllBranches, recurseList)
93
102
  );
94
103
  }
95
104
 
@@ -141,20 +150,45 @@ export function resolveSchema<T = any, S extends StrictRJSFSchema = RJSFSchema,
141
150
  schema: S,
142
151
  rootSchema: S,
143
152
  expandAllBranches: boolean,
153
+ recurseList: string[],
144
154
  formData?: T
145
155
  ): S[] {
146
- if (REF_KEY in schema) {
147
- return resolveReference<T, S, F>(validator, schema, rootSchema, expandAllBranches, formData);
156
+ const updatedSchemas = resolveReference<T, S, F>(
157
+ validator,
158
+ schema,
159
+ rootSchema,
160
+ expandAllBranches,
161
+ recurseList,
162
+ formData
163
+ );
164
+ if (updatedSchemas.length > 1 || updatedSchemas[0] !== schema) {
165
+ // return the updatedSchemas array if it has either multiple schemas within it
166
+ // OR the first schema is not the same as the original schema
167
+ return updatedSchemas;
148
168
  }
149
169
  if (DEPENDENCIES_KEY in schema) {
150
- const resolvedSchemas = resolveDependencies<T, S, F>(validator, schema, rootSchema, expandAllBranches, formData);
170
+ const resolvedSchemas = resolveDependencies<T, S, F>(
171
+ validator,
172
+ schema,
173
+ rootSchema,
174
+ expandAllBranches,
175
+ recurseList,
176
+ formData
177
+ );
151
178
  return resolvedSchemas.flatMap((s) => {
152
- return retrieveSchemaInternal<T, S, F>(validator, s, rootSchema, formData, expandAllBranches);
179
+ return retrieveSchemaInternal<T, S, F>(validator, s, rootSchema, formData, expandAllBranches, recurseList);
153
180
  });
154
181
  }
155
182
  if (ALL_OF_KEY in schema && Array.isArray(schema.allOf)) {
156
183
  const allOfSchemaElements: S[][] = schema.allOf.map((allOfSubschema) =>
157
- retrieveSchemaInternal<T, S, F>(validator, allOfSubschema as S, rootSchema, formData, expandAllBranches)
184
+ retrieveSchemaInternal<T, S, F>(
185
+ validator,
186
+ allOfSubschema as S,
187
+ rootSchema,
188
+ formData,
189
+ expandAllBranches,
190
+ recurseList
191
+ )
158
192
  );
159
193
  const allPermutations = getAllPermutationsOfXxxOf<S>(allOfSchemaElements);
160
194
  return allPermutations.map((permutation) => ({ ...schema, allOf: permutation }));
@@ -163,8 +197,9 @@ export function resolveSchema<T = any, S extends StrictRJSFSchema = RJSFSchema,
163
197
  return [schema];
164
198
  }
165
199
 
166
- /** Resolves references within a schema and then returns the `retrieveSchemaInternal()` of the resolved schema. Passes
167
- * the `expandAllBranches` flag down to the `retrieveSchemaInternal()` helper call.
200
+ /** Resolves all references within a schema and then returns the `retrieveSchemaInternal()` if the resolved schema is
201
+ * actually different than the original. Passes the `expandAllBranches` flag down to the `retrieveSchemaInternal()`
202
+ * helper call.
168
203
  *
169
204
  * @param validator - An implementation of the `ValidatorType` interface that will be forwarded to all the APIs
170
205
  * @param schema - The schema for which resolving a reference is desired
@@ -179,33 +214,48 @@ export function resolveReference<T = any, S extends StrictRJSFSchema = RJSFSchem
179
214
  schema: S,
180
215
  rootSchema: S,
181
216
  expandAllBranches: boolean,
217
+ recurseList: string[],
182
218
  formData?: T
183
219
  ): S[] {
184
- // Drop the $ref property of the source schema.
185
- const { $ref, ...localSchema } = schema;
186
- // Retrieve the referenced schema definition.
187
- const refSchema = findSchemaDefinition<S>($ref, rootSchema);
188
- // Update referenced schema definition with local schema properties.
189
- return retrieveSchemaInternal<T, S, F>(
190
- validator,
191
- { ...refSchema, ...localSchema },
192
- rootSchema,
193
- formData,
194
- expandAllBranches
195
- );
220
+ const updatedSchema = resolveAllReferences<S>(schema, rootSchema, recurseList);
221
+ if (updatedSchema !== schema) {
222
+ // Only call this if the schema was actually changed by the `resolveAllReferences()` function
223
+ return retrieveSchemaInternal<T, S, F>(
224
+ validator,
225
+ updatedSchema,
226
+ rootSchema,
227
+ formData,
228
+ expandAllBranches,
229
+ recurseList
230
+ );
231
+ }
232
+ return [schema];
196
233
  }
197
234
 
198
- /** Resolves all references within a schema's properties and array items.
235
+ /** Resolves all references within the schema itself as well as any of its properties and array items.
199
236
  *
200
237
  * @param schema - The schema for which resolving all references is desired
201
238
  * @param rootSchema - The root schema that will be forwarded to all the APIs
202
- * @returns - given schema will all references resolved
239
+ * @param recurseList - List of $refs already resolved to prevent recursion
240
+ * @returns - given schema will all references resolved or the original schema if no internal `$refs` were resolved
203
241
  */
204
- export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(schema: S, rootSchema: S): S {
242
+ export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(
243
+ schema: S,
244
+ rootSchema: S,
245
+ recurseList: string[]
246
+ ): S {
247
+ if (!isObject(schema)) {
248
+ return schema;
249
+ }
205
250
  let resolvedSchema: S = schema;
206
251
  // resolve top level ref
207
252
  if (REF_KEY in resolvedSchema) {
208
253
  const { $ref, ...localSchema } = resolvedSchema;
254
+ // Check for a recursive reference and stop the loop
255
+ if (recurseList.includes($ref!)) {
256
+ return resolvedSchema;
257
+ }
258
+ recurseList.push($ref!);
209
259
  // Retrieve the referenced schema definition.
210
260
  const refSchema = findSchemaDefinition<S>($ref, rootSchema);
211
261
  resolvedSchema = { ...refSchema, ...localSchema };
@@ -215,7 +265,7 @@ export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(sc
215
265
  const updatedProps = transform(
216
266
  resolvedSchema[PROPERTIES_KEY]!,
217
267
  (result, value, key: string) => {
218
- result[key] = resolveAllReferences(value as S, rootSchema);
268
+ result[key] = resolveAllReferences(value as S, rootSchema, recurseList);
219
269
  },
220
270
  {} as RJSFSchema
221
271
  );
@@ -227,10 +277,13 @@ export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(sc
227
277
  !Array.isArray(resolvedSchema.items) &&
228
278
  typeof resolvedSchema.items !== 'boolean'
229
279
  ) {
230
- resolvedSchema = { ...resolvedSchema, items: resolveAllReferences(resolvedSchema.items as S, rootSchema) };
280
+ resolvedSchema = {
281
+ ...resolvedSchema,
282
+ items: resolveAllReferences(resolvedSchema.items as S, rootSchema, recurseList),
283
+ };
231
284
  }
232
285
 
233
- return resolvedSchema;
286
+ return isEqual(schema, resolvedSchema) ? schema : resolvedSchema;
234
287
  }
235
288
 
236
289
  /** Creates new 'properties' items for each key in the `formData`
@@ -310,15 +363,36 @@ export function retrieveSchemaInternal<
310
363
  T = any,
311
364
  S extends StrictRJSFSchema = RJSFSchema,
312
365
  F extends FormContextType = any
313
- >(validator: ValidatorType<T, S, F>, schema: S, rootSchema: S, rawFormData?: T, expandAllBranches = false): S[] {
366
+ >(
367
+ validator: ValidatorType<T, S, F>,
368
+ schema: S,
369
+ rootSchema: S,
370
+ rawFormData?: T,
371
+ expandAllBranches = false,
372
+ recurseList: string[] = []
373
+ ): S[] {
314
374
  if (!isObject(schema)) {
315
375
  return [{} as S];
316
376
  }
317
- const resolvedSchemas = resolveSchema<T, S, F>(validator, schema, rootSchema, expandAllBranches, rawFormData);
377
+ const resolvedSchemas = resolveSchema<T, S, F>(
378
+ validator,
379
+ schema,
380
+ rootSchema,
381
+ expandAllBranches,
382
+ recurseList,
383
+ rawFormData
384
+ );
318
385
  return resolvedSchemas.flatMap((s: S) => {
319
386
  let resolvedSchema = s;
320
387
  if (IF_KEY in resolvedSchema) {
321
- return resolveCondition<T, S, F>(validator, resolvedSchema, rootSchema, expandAllBranches, rawFormData as T);
388
+ return resolveCondition<T, S, F>(
389
+ validator,
390
+ resolvedSchema,
391
+ rootSchema,
392
+ expandAllBranches,
393
+ recurseList,
394
+ rawFormData as T
395
+ );
322
396
  }
323
397
  if (ALL_OF_KEY in resolvedSchema) {
324
398
  // resolve allOf schemas
@@ -362,7 +436,14 @@ export function resolveAnyOrOneOfSchemas<
362
436
  T = any,
363
437
  S extends StrictRJSFSchema = RJSFSchema,
364
438
  F extends FormContextType = any
365
- >(validator: ValidatorType<T, S, F>, schema: S, rootSchema: S, expandAllBranches: boolean, rawFormData?: T) {
439
+ >(
440
+ validator: ValidatorType<T, S, F>,
441
+ schema: S,
442
+ rootSchema: S,
443
+ expandAllBranches: boolean,
444
+ recurseList: string[],
445
+ rawFormData?: T
446
+ ) {
366
447
  let anyOrOneOf: S[] | undefined;
367
448
  const { oneOf, anyOf, ...remaining } = schema;
368
449
  if (Array.isArray(oneOf)) {
@@ -375,7 +456,7 @@ export function resolveAnyOrOneOfSchemas<
375
456
  const formData = rawFormData === undefined && expandAllBranches ? ({} as T) : rawFormData;
376
457
  const discriminator = getDiscriminatorFieldFromSchema<S>(schema);
377
458
  anyOrOneOf = anyOrOneOf.map((s) => {
378
- return resolveAllReferences(s, rootSchema);
459
+ return resolveAllReferences(s, rootSchema, recurseList);
379
460
  });
380
461
  // Call this to trigger the set of isValid() calls that the schema parser will need
381
462
  const option = getFirstMatchingOption<T, S, F>(validator, formData, anyOrOneOf, rootSchema, discriminator);
@@ -403,6 +484,7 @@ export function resolveDependencies<T = any, S extends StrictRJSFSchema = RJSFSc
403
484
  schema: S,
404
485
  rootSchema: S,
405
486
  expandAllBranches: boolean,
487
+ recurseList: string[],
406
488
  formData?: T
407
489
  ): S[] {
408
490
  // Drop the dependencies from the source schema.
@@ -412,10 +494,19 @@ export function resolveDependencies<T = any, S extends StrictRJSFSchema = RJSFSc
412
494
  remainingSchema as S,
413
495
  rootSchema,
414
496
  expandAllBranches,
497
+ recurseList,
415
498
  formData
416
499
  );
417
500
  return resolvedSchemas.flatMap((resolvedSchema) =>
418
- processDependencies<T, S, F>(validator, dependencies, resolvedSchema, rootSchema, expandAllBranches, formData)
501
+ processDependencies<T, S, F>(
502
+ validator,
503
+ dependencies,
504
+ resolvedSchema,
505
+ rootSchema,
506
+ expandAllBranches,
507
+ recurseList,
508
+ formData
509
+ )
419
510
  );
420
511
  }
421
512
 
@@ -437,6 +528,7 @@ export function processDependencies<T = any, S extends StrictRJSFSchema = RJSFSc
437
528
  resolvedSchema: S,
438
529
  rootSchema: S,
439
530
  expandAllBranches: boolean,
531
+ recurseList: string[],
440
532
  formData?: T
441
533
  ): S[] {
442
534
  let schemas = [resolvedSchema];
@@ -464,11 +556,20 @@ export function processDependencies<T = any, S extends StrictRJSFSchema = RJSFSc
464
556
  dependencyKey,
465
557
  dependencyValue as S,
466
558
  expandAllBranches,
559
+ recurseList,
467
560
  formData
468
561
  );
469
562
  }
470
563
  return schemas.flatMap((schema) =>
471
- processDependencies<T, S, F>(validator, remainingDependencies, schema, rootSchema, expandAllBranches, formData)
564
+ processDependencies<T, S, F>(
565
+ validator,
566
+ remainingDependencies,
567
+ schema,
568
+ rootSchema,
569
+ expandAllBranches,
570
+ recurseList,
571
+ formData
572
+ )
472
573
  );
473
574
  }
474
575
  return schemas;
@@ -513,6 +614,7 @@ export function withDependentSchema<T = any, S extends StrictRJSFSchema = RJSFSc
513
614
  dependencyKey: string,
514
615
  dependencyValue: S,
515
616
  expandAllBranches: boolean,
617
+ recurseList: string[],
516
618
  formData?: T
517
619
  ): S[] {
518
620
  const dependentSchemas = retrieveSchemaInternal<T, S, F>(
@@ -520,7 +622,8 @@ export function withDependentSchema<T = any, S extends StrictRJSFSchema = RJSFSc
520
622
  dependencyValue,
521
623
  rootSchema,
522
624
  formData,
523
- expandAllBranches
625
+ expandAllBranches,
626
+ recurseList
524
627
  );
525
628
  return dependentSchemas.flatMap((dependent) => {
526
629
  const { oneOf, ...dependentSchema } = dependent;
@@ -534,7 +637,7 @@ export function withDependentSchema<T = any, S extends StrictRJSFSchema = RJSFSc
534
637
  if (typeof subschema === 'boolean' || !(REF_KEY in subschema)) {
535
638
  return [subschema as S];
536
639
  }
537
- return resolveReference<T, S, F>(validator, subschema as S, rootSchema, expandAllBranches, formData);
640
+ return resolveReference<T, S, F>(validator, subschema as S, rootSchema, expandAllBranches, recurseList, formData);
538
641
  });
539
642
  const allPermutations = getAllPermutationsOfXxxOf(resolvedOneOfs);
540
643
  return allPermutations.flatMap((resolvedOneOf) =>
@@ -545,6 +648,7 @@ export function withDependentSchema<T = any, S extends StrictRJSFSchema = RJSFSc
545
648
  dependencyKey,
546
649
  resolvedOneOf,
547
650
  expandAllBranches,
651
+ recurseList,
548
652
  formData
549
653
  )
550
654
  );
@@ -576,6 +680,7 @@ export function withExactlyOneSubschema<
576
680
  dependencyKey: string,
577
681
  oneOf: S['oneOf'],
578
682
  expandAllBranches: boolean,
683
+ recurseList: string[],
579
684
  formData?: T
580
685
  ): S[] {
581
686
  const validSubschemas = oneOf!.filter((subschema) => {
@@ -608,7 +713,8 @@ export function withExactlyOneSubschema<
608
713
  dependentSchema,
609
714
  rootSchema,
610
715
  formData,
611
- expandAllBranches
716
+ expandAllBranches,
717
+ recurseList
612
718
  );
613
719
  return schemas.map((s) => mergeSchemas(schema, s) as S);
614
720
  });
package/src/types.ts CHANGED
@@ -440,7 +440,7 @@ export type FieldTemplateProps<T = any, S extends StrictRJSFSchema = RJSFSchema,
440
440
  /** The formData for this field */
441
441
  formData?: T;
442
442
  /** The value change event handler; Can be called with a new value to change the value for this field */
443
- onChange: FieldProps['onChange'];
443
+ onChange: FieldProps<T, S, F>['onChange'];
444
444
  /** The key change event handler; Called when the key associated with a field is changed for an additionalProperty */
445
445
  onKeyChange: (value: string) => () => void;
446
446
  /** The property drop/removal event handler; Called when a field is removed in an additionalProperty context */