Minor refactoring of schema provider

This commit is contained in:
2025-05-13 16:22:58 +02:00
parent 7aced9477c
commit 9aac1d3e34

View File

@@ -78,6 +78,18 @@ export const jsonschemaProvider = {
}
}
const getResourceSchema = async (resourceName: string): Promise<CrudRJSFSchema> => {
return buildResource(await getJsonschema(), resourceName)
}
const getColumns = async (resourceName: string): Promise<GridColDef[]> => {
return buildColumns(await getJsonschema(), resourceName)
}
const getFilters = async (resourceName: string, resourcePath: string): Promise<FilterField[]> => {
return buildFilters(await getJsonschema(), resourceName, resourcePath);
}
type PathParameter = {
in: string,
name:string
@@ -87,10 +99,6 @@ type PathSchema = {
parameters: PathParameter[]
}
function shortenResourceName(resourceName: string) {
return convertCamelToSnake(resourceName.replace(/(-Input|-Output|Create|Update|Read)$/g, ""));
}
type FilterField = {
name: string,
label: string,
@@ -98,6 +106,11 @@ type FilterField = {
operators: { name: string, label: string }[]
}
type Operator = {
operator: string,
fieldName: string,
}
async function hasSearch(resourcePath: string): Promise<boolean> {
const jst = new JsonSchemaTraverser(await getJsonschema());
const pathSchema = jst.getPath(resourcePath);
@@ -110,9 +123,9 @@ async function hasSearch(resourcePath: string): Promise<boolean> {
return false
}
async function getFilters(resourceName: string, resourcePath: string): Promise<FilterField[]> {
function buildFilters(rawSchema: RJSFSchema, resourceName: string, resourcePath: string): FilterField[] {
const shortResourceName = shortenResourceName(resourceName);
const jst = new JsonSchemaTraverser(await getJsonschema());
const jst = new JsonSchemaTraverser(rawSchema);
const pathSchema = jst.getPath(resourcePath);
const seen: { [k: string]: number } = {};
@@ -125,8 +138,8 @@ async function getFilters(resourceName: string, resourcePath: string): Promise<F
const field = jst.getPropertyByPath(jst.getResource(`${resourceName}Read`), fieldName)
filters.push({
name: fieldName,
label: i18n.t(`schemas.${shortResourceName}.${convertCamelToSnake(fieldName)}`),
type: getFieldType(fieldName, field),
label: getPropertyI18nLabel(shortResourceName, fieldName),
type: getFieldFilterType(fieldName, field),
operators: [{ name: operator, label: operator }]
});
} else {
@@ -139,12 +152,6 @@ async function getFilters(resourceName: string, resourcePath: string): Promise<F
return filters;
}
type Operator = {
operator: string,
fieldName: string,
}
function processParamName(param: PathParameter): Operator {
const nameParts = param.name.split("__")
@@ -154,7 +161,7 @@ function processParamName(param: PathParameter): Operator {
}
}
const getFieldType = (fieldName: string, field: RJSFSchema): string => {
const getFieldFilterType = (fieldName: string, field: RJSFSchema): string => {
if (fieldName == "created_by" || fieldName == "updated_by") {
return "author";
} else if (Array.isArray(field)) {
@@ -180,17 +187,11 @@ const getFieldType = (fieldName: string, field: RJSFSchema): string => {
throw "Unimplemented field type"
}
const getColumns = async (resourceName: string): Promise<GridColDef[]> => {
return buildColumns(await getJsonschema(), resourceName)
}
function buildColumns (rawSchemas: RJSFSchema, resourceName: string, prefix: string|undefined = undefined): GridColDef[] {
if (rawSchemas.components.schemas[resourceName] === undefined) {
throw new Error(`Resource "${resourceName}" not found in schema.`);
}
const shortResourceName = shortenResourceName(resourceName);
const jst = new JsonSchemaTraverser(rawSchemas);
let resource = structuredClone(jst.getResource(resourceName));
const shortResourceName = convertCamelToSnake(resourceName.replace(/(-Input|-Output|Create|Update|Read)$/g, ""));
let resource = rawSchemas.components.schemas[resourceName];
let result: GridColDef[] = [];
for (const prop_name in resource.properties) {
let prop = resource.properties[prop_name];
@@ -264,42 +265,32 @@ function buildColumns (rawSchemas: RJSFSchema, resourceName: string, prefix: str
return result;
}
const getResourceSchema = async (resourceName: string): Promise<CrudRJSFSchema> => {
return buildResource(await getJsonschema(), resourceName)
}
function convertCamelToSnake(str: string): string {
return str.replace(/([a-zA-Z])(?=[A-Z])/g,'$1_').toLowerCase()
}
function buildResource(rawSchemas: RJSFSchema, resourceName: string) {
if (rawSchemas.components.schemas[resourceName] === undefined) {
throw new Error(`Resource "${resourceName}" not found in schema.`);
}
const shortResourceName = shortenResourceName(resourceName);
const jst = new JsonSchemaTraverser(rawSchemas);
let resource = structuredClone(jst.getResource(resourceName));
const shortResourceName = convertCamelToSnake(resourceName.replace(/(-Input|-Output|Create|Update|Read)$/g, ""));
let resource = structuredClone(rawSchemas.components.schemas[resourceName]);
resource.components = { schemas: {} };
for (let prop_name in resource.properties) {
let prop = resource.properties[prop_name];
if (is_reference(prop)) {
resolveReference(rawSchemas, resource, prop);
buildReference(rawSchemas, resource, prop);
} else if (is_union(prop)) {
const union = prop.hasOwnProperty("oneOf") ? prop.oneOf : prop.anyOf;
for (let i in union) {
if (is_reference(union[i])) {
resolveReference(rawSchemas, resource, union[i]);
buildReference(rawSchemas, resource, union[i]);
}
}
} else if (is_enum(prop)) {
for (let i in prop.allOf) {
if (is_reference(prop.allOf[i])) {
resolveReference(rawSchemas, resource, prop.allOf[i]);
buildReference(rawSchemas, resource, prop.allOf[i]);
}
}
} else if (is_array(prop) && is_reference(prop.items)) {
resolveReference(rawSchemas, resource, prop.items);
buildReference(rawSchemas, resource, prop.items);
}
if (prop.hasOwnProperty("title")) {
@@ -313,16 +304,7 @@ function buildResource(rawSchemas: RJSFSchema, resourceName: string) {
return resource;
}
let rawSchema: RJSFSchema;
const getJsonschema = async (): Promise<RJSFSchema> => {
if (rawSchema === undefined) {
const response = await fetch(`${API_URL}/openapi.json`,);
rawSchema = await response.json();
}
return rawSchema;
}
function resolveReference(rawSchemas: RJSFSchema, resource: any, prop_reference: any) {
function buildReference(rawSchemas: RJSFSchema, resource: any, prop_reference: any) {
const subresourceName = get_reference_name(prop_reference);
const subresource = buildResource(rawSchemas, subresourceName);
resource.components.schemas[subresourceName] = subresource;
@@ -391,6 +373,31 @@ function get_reference_name(prop: any) {
return prop['$ref'].substring(prop['$ref'].lastIndexOf('/')+1);
}
function convertCamelToSnake(str: string): string {
return str.replace(/([a-zA-Z])(?=[A-Z])/g,'$1_').toLowerCase()
}
function shortenResourceName(resourceName: string) {
return convertCamelToSnake(resourceName.replace(/(-Input|-Output|Create|Update|Read)$/g, ""));
}
function getPropertyI18nLabel(shortResourceName: string, fieldName: string): string {
if (meta_fields.indexOf(fieldName) > -1) {
return i18n.t(`schemas.${convertCamelToSnake(fieldName)}`);
}
const path = `schemas.${shortResourceName}.${convertCamelToSnake(fieldName)}`
return i18n.t(path)
}
let rawSchema: RJSFSchema;
const getJsonschema = async (): Promise<RJSFSchema> => {
if (rawSchema === undefined) {
const response = await fetch(`${API_URL}/openapi.json`,);
rawSchema = await response.json();
}
return rawSchema;
}
const JsonSchemaTraverser = class {
private rawSchemas: RJSFSchema;