@jsonforms/core 3.2.0-alpha.1 → 3.2.0-alpha.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.
@@ -27,11 +27,17 @@ export declare const computeLabel: (label: string | undefined, required: boolean
27
27
  */
28
28
  export declare const showAsRequired: (required: boolean, hideRequiredAsterisk: boolean) => boolean;
29
29
  /**
30
- * Create a default value based on the given scheam.
30
+ * Create a default value based on the given schema.
31
31
  * @param schema the schema for which to create a default value.
32
32
  * @returns {any}
33
33
  */
34
- export declare const createDefaultValue: (schema: JsonSchema) => {};
34
+ export declare const createDefaultValue: (schema: JsonSchema, rootSchema: JsonSchema) => any;
35
+ /**
36
+ * Returns the default value defined in the given schema.
37
+ * @param schema the schema for which to create a default value.
38
+ * @returns {any}
39
+ */
40
+ export declare const extractDefaults: (schema: JsonSchema, rootSchema: JsonSchema) => any;
35
41
  /**
36
42
  * Whether an element's description should be hidden.
37
43
  *
@@ -1,5 +1,31 @@
1
1
  import type { JsonSchema, Scoped, UISchemaElement } from '..';
2
2
  import type Ajv from 'ajv';
3
+ /**
4
+ * Returns the string representation of the given date. The format of the output string can be specified:
5
+ * - 'date' for a date-only string (YYYY-MM-DD),
6
+ * - 'time' for a time-only string (HH:mm:ss), or
7
+ * - 'date-time' for a full date-time string in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ).
8
+ * If no format is specified, the full date-time ISO string is returned by default.
9
+ *
10
+ * @returns {string} A string representation of the date in the specified format.
11
+ *
12
+ * @example
13
+ * // returns '2023-11-09'
14
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'date');
15
+ *
16
+ * @example
17
+ * // returns '14:22:54'
18
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'time');
19
+ *
20
+ * @example
21
+ * // returns '2023-11-09T14:22:54.131Z'
22
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'date-time');
23
+ *
24
+ * @example
25
+ * // returns '2023-11-09T14:22:54.131Z'
26
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'));
27
+ */
28
+ export declare const convertDateToString: (date: Date, format?: 'date' | 'time' | 'date-time') => string;
3
29
  /**
4
30
  * Escape the given string such that it can be used as a class name,
5
31
  * i.e. hashes and slashes will be replaced.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonforms/core",
3
- "version": "3.2.0-alpha.1",
3
+ "version": "3.2.0-alpha.3",
4
4
  "description": "Core module of JSON Forms",
5
5
  "repository": "https://github.com/eclipsesource/jsonforms",
6
6
  "bugs": "https://github.com/eclipsesource/jsonforms/issues",
@@ -99,5 +99,5 @@
99
99
  "typedoc": "~0.21.9",
100
100
  "typescript": "4.2.3"
101
101
  },
102
- "gitHead": "deb2c7cd71f6065cca7777420b1018f17e73052a"
102
+ "gitHead": "77624c6ab6c0f3db98abe3175547bbd51f7510bb"
103
103
  }
@@ -90,16 +90,6 @@ const initState: JsonFormsCore = {
90
90
  additionalErrors: [],
91
91
  };
92
92
 
93
- const reuseAjvForSchema = (ajv: Ajv, schema: JsonSchema): Ajv => {
94
- if (
95
- Object.prototype.hasOwnProperty.call(schema, 'id') ||
96
- Object.prototype.hasOwnProperty.call(schema, '$id')
97
- ) {
98
- ajv.removeSchema(schema);
99
- }
100
- return ajv;
101
- };
102
-
103
93
  const getOrCreateAjv = (
104
94
  state: JsonFormsCore,
105
95
  action?: InitAction | UpdateCoreAction
@@ -115,12 +105,7 @@ const getOrCreateAjv = (
115
105
  }
116
106
  }
117
107
  }
118
- if (state.ajv) {
119
- return action?.schema
120
- ? reuseAjvForSchema(state.ajv, action.schema)
121
- : state.ajv;
122
- }
123
- return createAjv();
108
+ return state.ajv ? state.ajv : createAjv();
124
109
  };
125
110
 
126
111
  const hasAjvOption = (option: any): option is InitActionOptions => {
@@ -255,7 +240,7 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
255
240
  const needsNewValidator =
256
241
  action.schema && state.ajv && state.validationMode !== 'NoValidation';
257
242
  const v = needsNewValidator
258
- ? reuseAjvForSchema(state.ajv, action.schema).compile(action.schema)
243
+ ? state.ajv.compile(action.schema)
259
244
  : state.validator;
260
245
  const errors = validate(v, state.data);
261
246
  return {
@@ -326,9 +311,7 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
326
311
  };
327
312
  }
328
313
  if (state.validationMode === 'NoValidation') {
329
- const validator = reuseAjvForSchema(state.ajv, state.schema).compile(
330
- state.schema
331
- );
314
+ const validator = state.ajv.compile(state.schema);
332
315
  const errors = validate(validator, state.data);
333
316
  return {
334
317
  ...state,
@@ -77,7 +77,7 @@ export const findUISchema = (
77
77
  return fallback();
78
78
  }
79
79
  // force generation of uischema
80
- return Generate.uiSchema(schema, fallback);
80
+ return Generate.uiSchema(schema, fallback, undefined, rootSchema);
81
81
  }
82
82
  } else if (typeof control.options.detail === 'object') {
83
83
  // check if detail is a valid uischema
@@ -57,7 +57,7 @@ import { createLabelDescriptionFrom } from './label';
57
57
  import type { CombinatorKeyword } from './combinators';
58
58
  import { moveDown, moveUp } from './array';
59
59
  import type { AnyAction, Dispatch } from './type';
60
- import { Resolve } from './util';
60
+ import { Resolve, convertDateToString, hasType } from './util';
61
61
  import { composePaths, composeWithUi } from './path';
62
62
  import { CoreActions, update } from '../actions';
63
63
  import type { ErrorObject } from 'ajv';
@@ -78,6 +78,8 @@ import {
78
78
  arrayDefaultTranslations,
79
79
  ArrayTranslations,
80
80
  } from '../i18n/arrayTranslations';
81
+ import { resolveSchema } from './resolvers';
82
+ import cloneDeep from 'lodash/cloneDeep';
81
83
 
82
84
  const isRequired = (
83
85
  schema: JsonSchema,
@@ -137,33 +139,65 @@ export const showAsRequired = (
137
139
  };
138
140
 
139
141
  /**
140
- * Create a default value based on the given scheam.
142
+ * Create a default value based on the given schema.
141
143
  * @param schema the schema for which to create a default value.
142
144
  * @returns {any}
143
145
  */
144
- export const createDefaultValue = (schema: JsonSchema) => {
145
- switch (schema.type) {
146
- case 'string':
147
- if (
148
- schema.format === 'date-time' ||
149
- schema.format === 'date' ||
150
- schema.format === 'time'
151
- ) {
152
- return new Date();
146
+ export const createDefaultValue = (
147
+ schema: JsonSchema,
148
+ rootSchema: JsonSchema
149
+ ) => {
150
+ const resolvedSchema = Resolve.schema(schema, schema.$ref, rootSchema);
151
+ if (resolvedSchema.default !== undefined) {
152
+ return extractDefaults(resolvedSchema, rootSchema);
153
+ }
154
+ if (hasType(resolvedSchema, 'string')) {
155
+ if (
156
+ resolvedSchema.format === 'date-time' ||
157
+ resolvedSchema.format === 'date' ||
158
+ resolvedSchema.format === 'time'
159
+ ) {
160
+ return convertDateToString(new Date(), resolvedSchema.format);
161
+ }
162
+ return '';
163
+ } else if (
164
+ hasType(resolvedSchema, 'integer') ||
165
+ hasType(resolvedSchema, 'number')
166
+ ) {
167
+ return 0;
168
+ } else if (hasType(resolvedSchema, 'boolean')) {
169
+ return false;
170
+ } else if (hasType(resolvedSchema, 'array')) {
171
+ return [];
172
+ } else if (hasType(resolvedSchema, 'object')) {
173
+ return extractDefaults(resolvedSchema, rootSchema);
174
+ } else if (hasType(resolvedSchema, 'null')) {
175
+ return null;
176
+ } else {
177
+ return {};
178
+ }
179
+ };
180
+
181
+ /**
182
+ * Returns the default value defined in the given schema.
183
+ * @param schema the schema for which to create a default value.
184
+ * @returns {any}
185
+ */
186
+ export const extractDefaults = (schema: JsonSchema, rootSchema: JsonSchema) => {
187
+ if (hasType(schema, 'object') && schema.default === undefined) {
188
+ const result: { [key: string]: any } = {};
189
+ for (const key in schema.properties) {
190
+ const property = schema.properties[key];
191
+ const resolvedProperty = property.$ref
192
+ ? Resolve.schema(rootSchema, property.$ref, rootSchema)
193
+ : property;
194
+ if (resolvedProperty.default !== undefined) {
195
+ result[key] = cloneDeep(resolvedProperty.default);
153
196
  }
154
- return '';
155
- case 'integer':
156
- case 'number':
157
- return 0;
158
- case 'boolean':
159
- return false;
160
- case 'array':
161
- return [];
162
- case 'null':
163
- return null;
164
- default:
165
- return {};
197
+ }
198
+ return result;
166
199
  }
200
+ return cloneDeep(schema.default);
167
201
  };
168
202
 
169
203
  /**
@@ -617,7 +651,11 @@ export const mapStateToMultiEnumControlProps = (
617
651
  ownProps: OwnPropsOfControl & OwnPropsOfEnum
618
652
  ): StatePropsOfControl & OwnPropsOfEnum => {
619
653
  const props: StatePropsOfControl = mapStateToControlProps(state, ownProps);
620
- const items = props.schema.items as JsonSchema;
654
+ let items = props.schema.items as JsonSchema;
655
+ items =
656
+ items && items.$ref
657
+ ? resolveSchema(props.rootSchema, items.$ref, props.rootSchema)
658
+ : items;
621
659
  const options: EnumOption[] =
622
660
  ownProps.options ||
623
661
  (items?.oneOf &&
package/src/util/util.ts CHANGED
@@ -33,6 +33,49 @@ import { composePaths, toDataPathSegments } from './path';
33
33
  import { isEnabled, isVisible } from './runtime';
34
34
  import type Ajv from 'ajv';
35
35
 
36
+ /**
37
+ * Returns the string representation of the given date. The format of the output string can be specified:
38
+ * - 'date' for a date-only string (YYYY-MM-DD),
39
+ * - 'time' for a time-only string (HH:mm:ss), or
40
+ * - 'date-time' for a full date-time string in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ).
41
+ * If no format is specified, the full date-time ISO string is returned by default.
42
+ *
43
+ * @returns {string} A string representation of the date in the specified format.
44
+ *
45
+ * @example
46
+ * // returns '2023-11-09'
47
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'date');
48
+ *
49
+ * @example
50
+ * // returns '14:22:54'
51
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'time');
52
+ *
53
+ * @example
54
+ * // returns '2023-11-09T14:22:54.131Z'
55
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'), 'date-time');
56
+ *
57
+ * @example
58
+ * // returns '2023-11-09T14:22:54.131Z'
59
+ * convertDateToString(new Date('2023-11-09T14:22:54.131Z'));
60
+ */
61
+ export const convertDateToString = (
62
+ date: Date,
63
+ format?: 'date' | 'time' | 'date-time'
64
+ ): string => {
65
+ //e.g. '2023-11-09T14:22:54.131Z'
66
+ const dateString = date.toISOString();
67
+ if (format === 'date-time') {
68
+ return dateString;
69
+ } else if (format === 'date') {
70
+ // e.g. '2023-11-09'
71
+ return dateString.split('T')[0];
72
+ } else if (format === 'time') {
73
+ //e.g. '14:22:54'
74
+ return dateString.split('T')[1].split('.')[0];
75
+ }
76
+ return dateString;
77
+ };
78
+
36
79
  /**
37
80
  * Escape the given string such that it can be used as a class name,
38
81
  * i.e. hashes and slashes will be replaced.
@@ -77,7 +120,17 @@ export const deriveTypes = (jsonSchema: JsonSchema): string[] => {
77
120
  if (!isEmpty(jsonSchema.items)) {
78
121
  return ['array'];
79
122
  }
80
-
123
+ if (!isEmpty(jsonSchema.enum)) {
124
+ const types: Set<string> = new Set();
125
+ jsonSchema.enum.forEach((enumElement) => {
126
+ if (typeof enumElement === 'string') {
127
+ types.add('string');
128
+ } else {
129
+ deriveTypes(enumElement).forEach((type) => types.add(type));
130
+ }
131
+ });
132
+ return Array.from(types);
133
+ }
81
134
  if (!isEmpty(jsonSchema.allOf)) {
82
135
  const allOfType = find(
83
136
  jsonSchema.allOf,
@@ -31,6 +31,7 @@ export const createAjv = (options?: Options) => {
31
31
  allErrors: true,
32
32
  verbose: true,
33
33
  strict: false,
34
+ addUsedSchema: false,
34
35
  ...options,
35
36
  });
36
37
  addFormats(ajv);