@rjsf/utils 6.0.0-beta.1 → 6.0.0-beta.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rjsf/utils",
3
- "version": "6.0.0-beta.1",
3
+ "version": "6.0.0-beta.3",
4
4
  "main": "dist/index.js",
5
5
  "module": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -65,6 +65,7 @@
65
65
  "react": ">=18"
66
66
  },
67
67
  "dependencies": {
68
+ "fast-uri": "^3.0.6",
68
69
  "json-schema-merge-allof": "^0.8.1",
69
70
  "jsonpointer": "^5.0.1",
70
71
  "lodash": "^4.17.21",
package/src/constants.ts CHANGED
@@ -25,6 +25,7 @@ export const READONLY_KEY = 'readonly';
25
25
  export const REQUIRED_KEY = 'required';
26
26
  export const SUBMIT_BTN_OPTIONS_KEY = 'submitButtonOptions';
27
27
  export const REF_KEY = '$ref';
28
+ export const SCHEMA_KEY = '$schema';
28
29
  /** The path of the discriminator value returned by the schema endpoint.
29
30
  * The discriminator is the value in a `oneOf` that determines which option is selected.
30
31
  */
@@ -42,3 +43,7 @@ export const UI_FIELD_KEY = 'ui:field';
42
43
  export const UI_WIDGET_KEY = 'ui:widget';
43
44
  export const UI_OPTIONS_KEY = 'ui:options';
44
45
  export const UI_GLOBAL_OPTIONS_KEY = 'ui:globalOptions';
46
+
47
+ /** The JSON Schema version strings
48
+ */
49
+ export const JSON_SCHEMA_DRAFT_2020_12 = 'https://json-schema.org/draft/2020-12/schema';
@@ -1,8 +1,33 @@
1
1
  import jsonpointer from 'jsonpointer';
2
2
  import omit from 'lodash/omit';
3
3
 
4
- import { REF_KEY } from './constants';
4
+ import { ID_KEY, JSON_SCHEMA_DRAFT_2020_12, REF_KEY, SCHEMA_KEY } from './constants';
5
5
  import { GenericObjectType, RJSFSchema, StrictRJSFSchema } from './types';
6
+ import isObject from 'lodash/isObject';
7
+ import isEmpty from 'lodash/isEmpty';
8
+ import UriResolver from 'fast-uri';
9
+
10
+ /** Looks for the `$id` pointed by `ref` in the schema definitions embedded in
11
+ * a JSON Schema bundle
12
+ *
13
+ * @param schema - The schema wherein `ref` should be searched
14
+ * @param ref - The `$id` of the reference to search for
15
+ * @returns - The schema matching the reference, or `undefined` if no match is found
16
+ */
17
+ function findEmbeddedSchemaRecursive<S extends StrictRJSFSchema = RJSFSchema>(schema: S, ref: string): S | undefined {
18
+ if (ID_KEY in schema && UriResolver.equal(schema[ID_KEY] as string, ref)) {
19
+ return schema;
20
+ }
21
+ for (const subSchema of Object.values(schema)) {
22
+ if (isObject(subSchema)) {
23
+ const result = findEmbeddedSchemaRecursive<S>(subSchema as S, ref);
24
+ if (result !== undefined) {
25
+ return result as S;
26
+ }
27
+ }
28
+ }
29
+ return undefined;
30
+ }
6
31
 
7
32
  /** Splits out the value at the `key` in `object` from the `object`, returning an array that contains in the first
8
33
  * location, the `object` minus the `key: value` and in the second location the `value`.
@@ -26,6 +51,7 @@ export function splitKeyElementFromObject(key: string, object: GenericObjectType
26
51
  * @param $ref - The ref string for which the schema definition is desired
27
52
  * @param [rootSchema={}] - The root schema in which to search for the definition
28
53
  * @param recurseList - List of $refs already resolved to prevent recursion
54
+ * @param baseURI - The base URI to be used for resolving relative references
29
55
  * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
30
56
  * @throws - Error indicating that no schema for that reference could be resolved
31
57
  */
@@ -33,16 +59,32 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
33
59
  $ref?: string,
34
60
  rootSchema: S = {} as S,
35
61
  recurseList: string[] = [],
62
+ baseURI: string | undefined = ID_KEY in rootSchema ? rootSchema[ID_KEY] : undefined,
36
63
  ): S {
37
64
  const ref = $ref || '';
38
- let decodedRef;
65
+ let current: S | undefined = undefined;
39
66
  if (ref.startsWith('#')) {
40
67
  // Decode URI fragment representation.
41
- decodedRef = decodeURIComponent(ref.substring(1));
42
- } else {
43
- throw new Error(`Could not find a definition for ${$ref}.`);
68
+ const decodedRef = decodeURIComponent(ref.substring(1));
69
+ if (baseURI === undefined || (ID_KEY in rootSchema && rootSchema[ID_KEY] === baseURI)) {
70
+ current = jsonpointer.get(rootSchema, decodedRef);
71
+ } else if (rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {
72
+ current = findEmbeddedSchemaRecursive<S>(rootSchema, baseURI.replace(/\/$/, ''));
73
+ if (current !== undefined) {
74
+ current = jsonpointer.get(current, decodedRef);
75
+ }
76
+ }
77
+ } else if (rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {
78
+ const resolvedRef = baseURI ? UriResolver.resolve(baseURI, ref) : ref;
79
+ const [refId, ...refAnchor] = resolvedRef.replace(/#\/?$/, '').split('#');
80
+ current = findEmbeddedSchemaRecursive<S>(rootSchema, refId.replace(/\/$/, ''));
81
+ if (current !== undefined) {
82
+ baseURI = current[ID_KEY];
83
+ if (!isEmpty(refAnchor)) {
84
+ current = jsonpointer.get(current, decodeURIComponent(refAnchor.join('#')));
85
+ }
86
+ }
44
87
  }
45
- const current: S = jsonpointer.get(rootSchema, decodedRef);
46
88
  if (current === undefined) {
47
89
  throw new Error(`Could not find a definition for ${$ref}.`);
48
90
  }
@@ -58,7 +100,7 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
58
100
  throw new Error(`Definition for ${firstRef} contains a circular reference through ${circularPath}`);
59
101
  }
60
102
  const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current);
61
- const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref]);
103
+ const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref], baseURI);
62
104
  if (Object.keys(remaining).length > 0) {
63
105
  return { ...remaining, ...subSchema };
64
106
  }
@@ -74,13 +116,15 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
74
116
  *
75
117
  * @param $ref - The ref string for which the schema definition is desired
76
118
  * @param [rootSchema={}] - The root schema in which to search for the definition
119
+ * @param [baseURI=rootSchema['$id']] - The base URI to be used for resolving relative references
77
120
  * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
78
121
  * @throws - Error indicating that no schema for that reference could be resolved
79
122
  */
80
123
  export default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>(
81
124
  $ref?: string,
82
125
  rootSchema: S = {} as S,
126
+ baseURI: string | undefined = ID_KEY in rootSchema ? rootSchema[ID_KEY] : undefined,
83
127
  ): S {
84
128
  const recurseList: string[] = [];
85
- return findSchemaDefinitionRecursive($ref, rootSchema, recurseList);
129
+ return findSchemaDefinitionRecursive($ref, rootSchema, recurseList, baseURI);
86
130
  }
@@ -223,7 +223,7 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
223
223
  // For object defaults, only override parent defaults that are defined in
224
224
  // schema.default.
225
225
  defaults = mergeObjects(defaults!, schema.default as GenericObjectType) as T;
226
- } else if (DEFAULT_KEY in schema && !schema[ANY_OF_KEY] && !schema[ONE_OF_KEY]) {
226
+ } else if (DEFAULT_KEY in schema && !schema[ANY_OF_KEY] && !schema[ONE_OF_KEY] && !schema[REF_KEY]) {
227
227
  // If the schema has a default value, then we should use it as the default.
228
228
  // And if the schema does not have anyOf or oneOf, this is done because we need to merge the defaults with the formData.
229
229
  defaults = schema.default as unknown as T;
@@ -234,6 +234,12 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
234
234
  updatedRecurseList = _recurseList.concat(refName!);
235
235
  schemaToCompute = findSchemaDefinition<S>(refName, rootSchema);
236
236
  }
237
+
238
+ // If the referenced schema exists and parentDefaults is not set
239
+ // Then set the defaults from the current schema for the referenced schema
240
+ if (schemaToCompute && !defaults) {
241
+ defaults = schema.default as T | undefined;
242
+ }
237
243
  } else if (DEPENDENCIES_KEY in schema) {
238
244
  // Get the default if set from properties to ensure the dependencies conditions are resolved based on it
239
245
  const defaultFormData: T = {
@@ -13,6 +13,7 @@ import {
13
13
  ALL_OF_KEY,
14
14
  ANY_OF_KEY,
15
15
  DEPENDENCIES_KEY,
16
+ ID_KEY,
16
17
  IF_KEY,
17
18
  ITEMS_KEY,
18
19
  ONE_OF_KEY,
@@ -333,12 +334,14 @@ export function resolveReference<T = any, S extends StrictRJSFSchema = RJSFSchem
333
334
  * @param schema - The schema for which resolving all references is desired
334
335
  * @param rootSchema - The root schema that will be forwarded to all the APIs
335
336
  * @param recurseList - List of $refs already resolved to prevent recursion
337
+ * @param baseURI - The base URI to be used for resolving relative references
336
338
  * @returns - given schema will all references resolved or the original schema if no internal `$refs` were resolved
337
339
  */
338
340
  export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(
339
341
  schema: S,
340
342
  rootSchema: S,
341
343
  recurseList: string[],
344
+ baseURI?: string,
342
345
  ): S {
343
346
  if (!isObject(schema)) {
344
347
  return schema;
@@ -353,8 +356,11 @@ export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(
353
356
  }
354
357
  recurseList.push($ref!);
355
358
  // Retrieve the referenced schema definition.
356
- const refSchema = findSchemaDefinition<S>($ref, rootSchema);
359
+ const refSchema = findSchemaDefinition<S>($ref, rootSchema, baseURI);
357
360
  resolvedSchema = { ...refSchema, ...localSchema };
361
+ if (ID_KEY in resolvedSchema) {
362
+ baseURI = resolvedSchema[ID_KEY];
363
+ }
358
364
  }
359
365
 
360
366
  if (PROPERTIES_KEY in resolvedSchema) {
@@ -363,7 +369,7 @@ export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(
363
369
  resolvedSchema[PROPERTIES_KEY]!,
364
370
  (result, value, key: string) => {
365
371
  const childList: string[] = [...recurseList];
366
- result[key] = resolveAllReferences(value as S, rootSchema, childList);
372
+ result[key] = resolveAllReferences(value as S, rootSchema, childList, baseURI);
367
373
  childrenLists.push(childList);
368
374
  },
369
375
  {} as RJSFSchema,
@@ -379,7 +385,7 @@ export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(
379
385
  ) {
380
386
  resolvedSchema = {
381
387
  ...resolvedSchema,
382
- items: resolveAllReferences(resolvedSchema.items as S, rootSchema, recurseList),
388
+ items: resolveAllReferences(resolvedSchema.items as S, rootSchema, recurseList, baseURI),
383
389
  };
384
390
  }
385
391
 
@@ -550,6 +556,9 @@ export function retrieveSchemaInternal<
550
556
  ? experimental_customMergeAllOf(resolvedSchema)
551
557
  : (mergeAllOf(resolvedSchema, {
552
558
  deep: false,
559
+ resolvers: {
560
+ $defs: mergeAllOf.options.resolvers.definitions,
561
+ },
553
562
  } as Options) as S);
554
563
  if (withContainsSchemas.length) {
555
564
  resolvedSchema.allOf = withContainsSchemas;
package/src/types.ts CHANGED
@@ -245,7 +245,7 @@ export type FormValidation<T = any> = FieldValidation & {
245
245
  export type RJSFBaseProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
246
246
  /** The schema object for the field being described */
247
247
  schema: S;
248
- /** The uiSchema object for this description field */
248
+ /** The uiSchema object for this base component */
249
249
  uiSchema?: UiSchema<T, S, F>;
250
250
  /** The `registry` object */
251
251
  registry: Registry<T, S, F>;
@@ -387,6 +387,9 @@ export type GlobalUISchemaOptions = {
387
387
  * This option allows you to change the separator between the original key name and the integer. Default is "-"
388
388
  */
389
389
  duplicateKeySuffixSeparator?: string;
390
+ /** Enables the displaying of description text that contains markdown
391
+ */
392
+ enableMarkdownInDescription?: boolean;
390
393
  };
391
394
 
392
395
  /** The object containing the registered core, theme and custom fields and widgets as well as the root schema, form
@@ -422,11 +425,8 @@ export interface Registry<T = any, S extends StrictRJSFSchema = RJSFSchema, F ex
422
425
  /** The properties that are passed to a Field implementation */
423
426
  export interface FieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
424
427
  extends GenericObjectType,
428
+ RJSFBaseProps<T, S, F>,
425
429
  Pick<HTMLAttributes<HTMLElement>, Exclude<keyof HTMLAttributes<HTMLElement>, 'onBlur' | 'onFocus' | 'onChange'>> {
426
- /** The JSON subschema object for this field */
427
- schema: S;
428
- /** The uiSchema for this field */
429
- uiSchema?: UiSchema<T, S, F>;
430
430
  /** The tree of unique ids for every child field */
431
431
  idSchema: IdSchema<T>;
432
432
  /** The data for this field */
@@ -463,8 +463,6 @@ export interface FieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F
463
463
  idSeparator?: string;
464
464
  /** An array of strings listing all generated error messages from encountered errors for this field */
465
465
  rawErrors?: string[];
466
- /** The `registry` object */
467
- registry: Registry<T, S, F>;
468
466
  }
469
467
 
470
468
  /** The definition of a React-based Field component */
@@ -726,7 +724,7 @@ export type ObjectFieldTemplateProps<
726
724
  /** A string value containing the title for the object */
727
725
  title: string;
728
726
  /** A string value containing the description for the object */
729
- description?: string;
727
+ description?: string | ReactElement;
730
728
  /** A boolean value stating if the object is disabled */
731
729
  disabled?: boolean;
732
730
  /** An array of objects representing the properties in the object */