Skip to content

Commit

Permalink
toPathSchema iterative
Browse files Browse the repository at this point in the history
  • Loading branch information
igorbrasileiro committed Sep 5, 2024
1 parent 8502b90 commit 6ca6edd
Showing 1 changed file with 102 additions and 82 deletions.
184 changes: 102 additions & 82 deletions packages/utils/src/schema/toPathSchema.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import isEqual from 'fast-deep-equal';
import set from 'lodash/set';

import {
ADDITIONAL_PROPERTIES_KEY,
ALL_OF_KEY,
ANY_OF_KEY,
ADDITIONAL_PROPERTIES_KEY,
DEPENDENCIES_KEY,
ITEMS_KEY,
NAME_KEY,
Expand Down Expand Up @@ -38,95 +38,115 @@ function toPathSchemaInternal<T = any, S extends StrictRJSFSchema = RJSFSchema,
formData?: T,
_recurseList: S[] = []
): PathSchema<T> {
if (REF_KEY in schema || DEPENDENCIES_KEY in schema || ALL_OF_KEY in schema) {
const _schema = retrieveSchema<T, S, F>(validator, schema, rootSchema, formData);
const sameSchemaIndex = _recurseList.findIndex((item) => isEqual(item, _schema));
if (sameSchemaIndex === -1) {
return toPathSchemaInternal<T, S, F>(
validator,
_schema,
const firstState = {
schema,
name,
formData,
_recurseList,
pathSchema: {} as PathSchema<T>,
};
const stack = [firstState];

while (stack.length > 0) {
const { schema, formData, _recurseList, pathSchema, name } = stack.pop()!;

if (REF_KEY in schema || DEPENDENCIES_KEY in schema || ALL_OF_KEY in schema) {
const _schema = retrieveSchema<T, S, F>(validator, schema, rootSchema, formData);
const sameSchemaIndex = _recurseList.findIndex((item) => isEqual(item, _schema));
if (sameSchemaIndex === -1) {
stack.push({
schema: _schema,
name,
formData,
_recurseList: _recurseList.concat(_schema),
pathSchema,
});
continue;
}
}

pathSchema[NAME_KEY] = name.replace(/^\./, '');

if (ONE_OF_KEY in schema || ANY_OF_KEY in schema) {
const xxxOf: S[] = ONE_OF_KEY in schema ? (schema.oneOf as S[]) : (schema.anyOf as S[]);
const discriminator = getDiscriminatorFieldFromSchema<S>(schema);
const index = getClosestMatchingOption<T, S, F>(validator, rootSchema!, formData, xxxOf, 0, discriminator);
const _schema: S = xxxOf![index] as S;
stack.push({
schema: _schema,
name,
rootSchema,
formData,
_recurseList.concat(_schema)
);
_recurseList,
pathSchema,
});
}
}

let pathSchema: PathSchema<T> = {
[NAME_KEY]: name.replace(/^\./, ''),
} as PathSchema<T>;

if (ONE_OF_KEY in schema || ANY_OF_KEY in schema) {
const xxxOf: S[] = ONE_OF_KEY in schema ? (schema.oneOf as S[]) : (schema.anyOf as S[]);
const discriminator = getDiscriminatorFieldFromSchema<S>(schema);
const index = getClosestMatchingOption<T, S, F>(validator, rootSchema!, formData, xxxOf, 0, discriminator);
const _schema: S = xxxOf![index] as S;
pathSchema = {
...pathSchema,
...toPathSchemaInternal<T, S, F>(validator, _schema, name, rootSchema, formData, _recurseList),
};
}
if (ADDITIONAL_PROPERTIES_KEY in schema && schema[ADDITIONAL_PROPERTIES_KEY] !== false) {
set(pathSchema, RJSF_ADDITIONAL_PROPERTIES_FLAG, true);
}

if (ADDITIONAL_PROPERTIES_KEY in schema && schema[ADDITIONAL_PROPERTIES_KEY] !== false) {
set(pathSchema, RJSF_ADDITIONAL_PROPERTIES_FLAG, true);
}
if (ITEMS_KEY in schema && Array.isArray(formData)) {
const { items: schemaItems, additionalItems: schemaAdditionalItems } = schema;

if (ITEMS_KEY in schema && Array.isArray(formData)) {
const { items: schemaItems, additionalItems: schemaAdditionalItems } = schema;
if (Array.isArray(schemaItems)) {
formData.forEach((element, i: number) => {
if (schemaItems[i]) {
const newPathSchema = {} as PathSchema<T>;
(pathSchema as PathSchema<T[]>)[i] = newPathSchema;
stack.push({
schema: schemaItems[i] as S,
name: `${name}.${i}`,
formData: element,
_recurseList,
pathSchema: newPathSchema,
});
} else if (schemaAdditionalItems) {
const newPathSchema = {} as PathSchema<T>;
(pathSchema as PathSchema<T[]>)[i] = newPathSchema;
stack.push({
schema: schemaAdditionalItems as S,
name: `${name}.${i}`,
formData: element,
_recurseList,
pathSchema: newPathSchema,
});
} else {
console.warn(`Unable to generate path schema for "${name}.${i}". No schema defined for it`);
}
});
} else {
formData.forEach((element, i: number) => {
const newPathSchema = {} as PathSchema<T>;
(pathSchema as PathSchema<T[]>)[i] = newPathSchema;
stack.push({
schema: schemaItems as S,
name: `${name}.${i}`,
formData: element,
_recurseList,
pathSchema: newPathSchema,
});
});
}
} else if (PROPERTIES_KEY in schema) {
for (const property in schema.properties) {
const field = get(schema, [PROPERTIES_KEY, property]);

if (Array.isArray(schemaItems)) {
formData.forEach((element, i: number) => {
if (schemaItems[i]) {
(pathSchema as PathSchema<T[]>)[i] = toPathSchemaInternal<T, S, F>(
validator,
schemaItems[i] as S,
`${name}.${i}`,
rootSchema,
element,
_recurseList
);
} else if (schemaAdditionalItems) {
(pathSchema as PathSchema<T[]>)[i] = toPathSchemaInternal<T, S, F>(
validator,
schemaAdditionalItems as S,
`${name}.${i}`,
rootSchema,
element,
_recurseList
);
} else {
console.warn(`Unable to generate path schema for "${name}.${i}". No schema defined for it`);
}
});
} else {
formData.forEach((element, i: number) => {
(pathSchema as PathSchema<T[]>)[i] = toPathSchemaInternal<T, S, F>(
validator,
schemaItems as S,
`${name}.${i}`,
rootSchema,
element,
_recurseList
);
});
}
} else if (PROPERTIES_KEY in schema) {
for (const property in schema.properties) {
const field = get(schema, [PROPERTIES_KEY, property]);
(pathSchema as PathSchema<GenericObjectType>)[property] = toPathSchemaInternal<T, S, F>(
validator,
field,
`${name}.${property}`,
rootSchema,
// It's possible that formData is not an object -- this can happen if an
// array item has just been added, but not populated with data yet
get(formData, [property]),
_recurseList
);
const newPathSchema = {} as PathSchema<T>;
(pathSchema as PathSchema<GenericObjectType>)[property] = newPathSchema;
stack.push({
schema: field,
name: `${name}.${property}`,
// It's possible that formData is not an object -- this can happen if an
// array item has just been added, but not populated with data yet
formData: get(formData, [property]),
_recurseList,
pathSchema: newPathSchema,
});
}
}
}
return pathSchema;

return firstState.pathSchema;
}

/** Generates an `PathSchema` object for the `schema`, recursively
Expand Down

0 comments on commit 6ca6edd

Please sign in to comment.