[FEAT] model generation is ready
This commit is contained in:
parent
be1e189d60
commit
d28c31290f
@ -14,8 +14,18 @@ import org.kar.archidata.externalRestApi.model.ClassMapModel;
|
||||
import org.kar.archidata.externalRestApi.model.ClassModel;
|
||||
import org.kar.archidata.externalRestApi.model.ClassObjectModel;
|
||||
import org.kar.archidata.externalRestApi.model.ClassObjectModel.FieldProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TsClassElement {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(TsClassElement.class);
|
||||
|
||||
public enum DefinedPosition {
|
||||
NATIVE, // Native element of TS language.
|
||||
BASIC, // basic wrapping for JAVA type.
|
||||
NORMAL // Normal Object to interpret.
|
||||
}
|
||||
|
||||
public List<ClassModel> models;
|
||||
public String zodName;
|
||||
public String tsTypeName;
|
||||
@ -23,11 +33,10 @@ public class TsClassElement {
|
||||
public String declaration;
|
||||
public String fileName = null;
|
||||
public String comment = null;
|
||||
public boolean isEnum = false;
|
||||
public boolean nativeType;
|
||||
public DefinedPosition nativeType = DefinedPosition.NORMAL;
|
||||
|
||||
public TsClassElement(final List<ClassModel> model, final String zodName, final String tsTypeName,
|
||||
final String tsCheckType, final String declaration, final boolean nativeType) {
|
||||
final String tsCheckType, final String declaration, final DefinedPosition nativeType) {
|
||||
this.models = model;
|
||||
this.zodName = zodName;
|
||||
this.tsTypeName = tsTypeName;
|
||||
@ -44,7 +53,6 @@ public class TsClassElement {
|
||||
this.tsTypeName = model.getOriginClasses().getSimpleName();
|
||||
this.tsCheckType = "is" + model.getOriginClasses().getSimpleName();
|
||||
this.declaration = null;
|
||||
this.nativeType = false;
|
||||
this.fileName = this.tsTypeName.replaceAll("([a-z])([A-Z])", "$1-$2").replaceAll("([A-Z])([A-Z][a-z])", "$1-$2")
|
||||
.toLowerCase();
|
||||
}
|
||||
@ -58,7 +66,7 @@ public class TsClassElement {
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from \"zod\";
|
||||
import { z as zod } from "zod";
|
||||
|
||||
""";
|
||||
}
|
||||
@ -127,23 +135,30 @@ public class TsClassElement {
|
||||
out.append(this.tsTypeName);
|
||||
out.append(");\n");
|
||||
}
|
||||
out.append(generateExportCheckFunction());
|
||||
out.append(generateExportCheckFunctionWrite(""));
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private Object generateExportCheckFunction() {
|
||||
private String generateExportCheckFunctionWrite(final String writeString) {
|
||||
final StringBuilder out = new StringBuilder();
|
||||
out.append("\nexport function ");
|
||||
out.append(this.tsCheckType);
|
||||
out.append(writeString);
|
||||
out.append("(data: any): data is ");
|
||||
out.append(this.tsTypeName);
|
||||
out.append(writeString);
|
||||
out.append(" {\n\ttry {\n\t\t");
|
||||
out.append(this.zodName);
|
||||
out.append(writeString);
|
||||
out.append("""
|
||||
.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data ${e}`);
|
||||
console.log(`Fail to parse data type='""");
|
||||
out.append(this.zodName);
|
||||
out.append(writeString);
|
||||
out.append("""
|
||||
' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -156,10 +171,10 @@ public class TsClassElement {
|
||||
final StringBuilder out = new StringBuilder();
|
||||
for (final ClassModel depModel : depModels) {
|
||||
final TsClassElement tsModel = tsGroup.find(depModel);
|
||||
if (!tsModel.nativeType) {
|
||||
if (tsModel.nativeType != DefinedPosition.NATIVE) {
|
||||
out.append("import {");
|
||||
out.append(tsModel.zodName);
|
||||
out.append("} from \"");
|
||||
out.append("} from \"./");
|
||||
out.append(tsModel.fileName);
|
||||
out.append("\";\n");
|
||||
}
|
||||
@ -193,6 +208,45 @@ public class TsClassElement {
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public String optionalTypeZod(final FieldProperty field) {
|
||||
if (field.model().getOriginClasses() == null || field.model().getOriginClasses().isPrimitive()) {
|
||||
return "";
|
||||
}
|
||||
return ".optional()";
|
||||
}
|
||||
|
||||
public String maxSizeZod(final FieldProperty field) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final Class<?> clazz = field.model().getOriginClasses();
|
||||
if (field.limitSize() > 0 && clazz == String.class) {
|
||||
builder.append(".max(");
|
||||
builder.append(field.limitSize());
|
||||
builder.append(")");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String readOnlyZod(final FieldProperty field) {
|
||||
if (field.readOnly()) {
|
||||
return ".readonly()";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String generateBaseObject() {
|
||||
final StringBuilder out = new StringBuilder();
|
||||
out.append(getBaseHeader());
|
||||
out.append("\n");
|
||||
|
||||
out.append("export const ");
|
||||
out.append(this.zodName);
|
||||
out.append(" = ");
|
||||
out.append(this.declaration);
|
||||
out.append(";");
|
||||
generateZodInfer(this.tsTypeName, this.zodName);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public String generateObject(final ClassObjectModel model, final TsClassElementGroup tsGroup) throws IOException {
|
||||
final StringBuilder out = new StringBuilder();
|
||||
out.append(getBaseHeader());
|
||||
@ -201,7 +255,7 @@ public class TsClassElement {
|
||||
|
||||
out.append(generateComment(model));
|
||||
out.append("export const ");
|
||||
out.append(this.tsTypeName);
|
||||
out.append(this.zodName);
|
||||
out.append(" = ");
|
||||
|
||||
if (model.getExtendsClass() != null) {
|
||||
@ -216,10 +270,10 @@ public class TsClassElement {
|
||||
for (final FieldProperty field : model.getFields()) {
|
||||
final ClassModel fieldModel = field.model();
|
||||
if (field.comment() != null) {
|
||||
out.append("\t/*\n");
|
||||
out.append("\t/**\n");
|
||||
out.append("\t * ");
|
||||
out.append(field.comment());
|
||||
out.append("\n\t*/\n");
|
||||
out.append("\n\t */\n");
|
||||
}
|
||||
out.append("\t");
|
||||
out.append(field.name());
|
||||
@ -234,18 +288,49 @@ public class TsClassElement {
|
||||
final String data = generateTsMap(fieldMapModel, tsGroup);
|
||||
out.append(data);
|
||||
}
|
||||
out.append(";\n");
|
||||
out.append(maxSizeZod(field));
|
||||
out.append(readOnlyZod(field));
|
||||
out.append(optionalTypeZod(field));
|
||||
out.append(",\n");
|
||||
}
|
||||
final List<String> omitField = model.getReadOnlyField();
|
||||
out.append("\n});\n");
|
||||
out.append("\nexport type ");
|
||||
out.append(this.tsTypeName);
|
||||
out.append(" = zod.infer<typeof ");
|
||||
out.append(generateZodInfer(this.tsTypeName, this.zodName));
|
||||
out.append(generateExportCheckFunctionWrite(""));
|
||||
|
||||
// Generate the Write Type associated.
|
||||
out.append("\nexport const ");
|
||||
out.append(this.zodName);
|
||||
out.append(">;\n");
|
||||
out.append(generateExportCheckFunction());
|
||||
out.append("Write = ");
|
||||
out.append(this.zodName);
|
||||
if (omitField.size() != 0) {
|
||||
out.append(".omit({\n");
|
||||
for (final String elem : omitField) {
|
||||
out.append("\t");
|
||||
out.append(elem);
|
||||
out.append(": true,\n");
|
||||
}
|
||||
out.append("\n})");
|
||||
}
|
||||
out.append(";\n");
|
||||
out.append(generateZodInfer(this.tsTypeName + "Write", this.zodName + "Write"));
|
||||
|
||||
// Check only the input value ==> no need of the output
|
||||
out.append(generateExportCheckFunctionWrite("Write"));
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
|
||||
private String generateZodInfer(final String tsName, final String zodName) {
|
||||
final StringBuilder out = new StringBuilder();
|
||||
out.append("\nexport type ");
|
||||
out.append(tsName);
|
||||
out.append(" = zod.infer<typeof ");
|
||||
out.append(zodName);
|
||||
out.append(">;\n");
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private String generateTsMap(final ClassMapModel model, final TsClassElementGroup tsGroup) {
|
||||
final StringBuilder out = new StringBuilder();
|
||||
out.append("zod.record(");
|
||||
@ -308,15 +393,16 @@ public class TsClassElement {
|
||||
}
|
||||
|
||||
public void generateFile(final String pathPackage, final TsClassElementGroup tsGroup) throws IOException {
|
||||
if (this.nativeType) {
|
||||
if (this.nativeType == DefinedPosition.NATIVE) {
|
||||
return;
|
||||
}
|
||||
final ClassModel model = this.models.get(0);
|
||||
String data = "";
|
||||
if (model instanceof final ClassEnumModel modelEnum) {
|
||||
if (this.nativeType == DefinedPosition.BASIC && model instanceof final ClassObjectModel modelObject) {
|
||||
data = generateBaseObject();
|
||||
} else if (model instanceof final ClassEnumModel modelEnum) {
|
||||
data = generateEnum(modelEnum, tsGroup);
|
||||
}
|
||||
if (model instanceof final ClassObjectModel modelObject) {
|
||||
} else if (model instanceof final ClassObjectModel modelObject) {
|
||||
data = generateObject(modelObject, tsGroup);
|
||||
}
|
||||
final Path path = Paths.get(pathPackage + File.separator + "model");
|
||||
|
@ -1,7 +1,11 @@
|
||||
package org.kar.archidata.externalRestApi;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
@ -12,10 +16,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kar.archidata.dataAccess.DataFactoryTsApi;
|
||||
import org.kar.archidata.externalRestApi.TsClassElement.DefinedPosition;
|
||||
import org.kar.archidata.externalRestApi.model.ClassModel;
|
||||
|
||||
public class TsGenerateApi {
|
||||
|
||||
|
||||
public static List<ClassModel> getCompatibleModels(
|
||||
final List<ClassModel> requestedModel,
|
||||
final List<Class<?>> search) {
|
||||
@ -30,7 +36,7 @@ public class TsGenerateApi {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public static void generateApi(final AnalyzeApi api, final String pathPackage) throws IOException {
|
||||
final List<TsClassElement> localModel = generateApiModel(api);
|
||||
final TsClassElementGroup tsGroup = new TsClassElementGroup(localModel);
|
||||
@ -38,6 +44,31 @@ public class TsGenerateApi {
|
||||
for (final TsClassElement element : localModel) {
|
||||
element.generateFile(pathPackage, tsGroup);
|
||||
}
|
||||
createIndex(pathPackage, tsGroup);
|
||||
|
||||
copyResourceFile("rest-tools.ts", pathPackage + File.separator + "rest-tools.ts");
|
||||
//copyResourceFile("zod-tools.ts", pathPackage + File.separator + "zod-tools.ts");
|
||||
}
|
||||
|
||||
private static void createIndex(final String pathPackage, final TsClassElementGroup tsGroup) throws IOException {
|
||||
final StringBuilder out = new StringBuilder("""
|
||||
/**
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
""");
|
||||
for (final TsClassElement elem : tsGroup.getTsElements()) {
|
||||
if (elem.nativeType == DefinedPosition.NATIVE) {
|
||||
continue;
|
||||
}
|
||||
out.append("export * from \"./");
|
||||
out.append(elem.fileName);
|
||||
out.append("\"\n");
|
||||
}
|
||||
final FileWriter myWriter = new FileWriter(
|
||||
pathPackage + File.separator + "model" + File.separator + "index.ts");
|
||||
myWriter.write(out.toString());
|
||||
myWriter.close();
|
||||
|
||||
}
|
||||
|
||||
private static List<TsClassElement> generateApiModel(final AnalyzeApi api) {
|
||||
@ -45,72 +76,87 @@ public class TsGenerateApi {
|
||||
final List<TsClassElement> tsModels = new ArrayList<>();
|
||||
List<ClassModel> models = getCompatibleModels(api.classModels, List.of(Void.class, void.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "void", "void", null, null, true));
|
||||
tsModels.add(new TsClassElement(models, "void", "void", null, null, DefinedPosition.NATIVE));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Object.class));
|
||||
if (models != null) {
|
||||
tsModels.add(
|
||||
new TsClassElement(models, "zod.object()", "object", null, "zod.object()", DefinedPosition.NATIVE));
|
||||
}
|
||||
// Map is binded to any ==> can not determine this complex model for now
|
||||
models = getCompatibleModels(api.classModels, List.of(Map.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "any", "any", null, null, true));
|
||||
tsModels.add(new TsClassElement(models, "zod.any()", "any", null, null, DefinedPosition.NATIVE));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(String.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "zod.string()", "string", null, "zod.string()", true));
|
||||
tsModels.add(
|
||||
new TsClassElement(models, "zod.string()", "string", null, "zod.string()", DefinedPosition.NATIVE));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(InputStream.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "z.instanceof(File)", "File", null, "z.instanceof(File)", true));
|
||||
tsModels.add(new TsClassElement(models, "z.instanceof(File)", "File", null, "z.instanceof(File)",
|
||||
DefinedPosition.NATIVE));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Boolean.class, boolean.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "zod.boolean()", "boolean", null, "zod.boolean()", true));
|
||||
tsModels.add(new TsClassElement(models, "zod.boolean()", "boolean", null, "zod.boolean()",
|
||||
DefinedPosition.NATIVE));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(UUID.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodUUID", "UUID", "isUUID", "zod.string().uuid()", false));
|
||||
tsModels.add(new TsClassElement(models, "ZodUUID", "UUID", "isUUID", "zod.string().uuid()",
|
||||
DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Long.class, long.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodLong", "Long", "isLong", "zod.number()", false));
|
||||
tsModels.add(
|
||||
new TsClassElement(models, "ZodLong", "Long", "isLong", "zod.number()", DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Short.class, short.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodShort", "Short", "isShort", "zod.number().safe()", true));
|
||||
tsModels.add(new TsClassElement(models, "ZodShort", "Short", "isShort", "zod.number().safe()",
|
||||
DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Integer.class, int.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodInteger", "Integer", "isInteger", "zod.number().safe()", true));
|
||||
tsModels.add(new TsClassElement(models, "ZodInteger", "Integer", "isInteger", "zod.number().safe()",
|
||||
DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Double.class, double.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodDouble", "Double", "isDouble", "zod.number()", true));
|
||||
tsModels.add(new TsClassElement(models, "ZodDouble", "Double", "isDouble", "zod.number()",
|
||||
DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Float.class, float.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodFloat", "Float", "isFloat", "zod.number()", false));
|
||||
tsModels.add(
|
||||
new TsClassElement(models, "ZodFloat", "Float", "isFloat", "zod.number()", DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Instant.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodInstant", "Instant", "isInstant", "zod.string()", false));
|
||||
tsModels.add(new TsClassElement(models, "ZodInstant", "Instant", "isInstant", "zod.string()",
|
||||
DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Date.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodDate", "Date", "isDate",
|
||||
"zod.string().datetime({ precision: 3 })", false));
|
||||
tsModels.add(new TsClassElement(models, "ZodIsoDate", "IsoDate", "isIsoDate",
|
||||
"zod.string().datetime({ precision: 3 })", DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(Timestamp.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodTimestamp", "Timestamp", "isTimestamp",
|
||||
"zod.string().datetime({ precision: 3 })", false));
|
||||
"zod.string().datetime({ precision: 3 })", DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(LocalDate.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodLocalDate", "LocalDate", "isLocalDate", "zod.string().date()",
|
||||
false));
|
||||
DefinedPosition.BASIC));
|
||||
}
|
||||
models = getCompatibleModels(api.classModels, List.of(LocalTime.class));
|
||||
if (models != null) {
|
||||
tsModels.add(new TsClassElement(models, "ZodLocalTime", "LocalTime", "isLocalTime", "zod.string().time()",
|
||||
false));
|
||||
DefinedPosition.BASIC));
|
||||
}
|
||||
for (final ClassModel model : api.classModels) {
|
||||
boolean alreadyExist = false;
|
||||
@ -126,5 +172,22 @@ public class TsGenerateApi {
|
||||
tsModels.add(new TsClassElement(model));
|
||||
}
|
||||
return tsModels;
|
||||
|
||||
}
|
||||
|
||||
public static void copyResourceFile(final String name, final String destinationPath) throws IOException {
|
||||
final InputStream ioStream = DataFactoryTsApi.class.getClassLoader().getResourceAsStream(name);
|
||||
if (ioStream == null) {
|
||||
throw new IllegalArgumentException("rest-tools.ts is not found");
|
||||
}
|
||||
final BufferedReader buffer = new BufferedReader(new InputStreamReader(ioStream));
|
||||
final FileWriter myWriter = new FileWriter(destinationPath);
|
||||
String line;
|
||||
while ((line = buffer.readLine()) != null) {
|
||||
myWriter.write(line);
|
||||
myWriter.write("\n");
|
||||
}
|
||||
ioStream.close();
|
||||
myWriter.close();
|
||||
}
|
||||
}
|
||||
|
@ -11,19 +11,19 @@ import java.util.Set;
|
||||
public abstract class ClassModel {
|
||||
protected Class<?> originClasses = null;
|
||||
protected List<ClassModel> dependencyModels = new ArrayList<>();
|
||||
|
||||
|
||||
public Class<?> getOriginClasses() {
|
||||
return this.originClasses;
|
||||
}
|
||||
|
||||
|
||||
protected boolean isCompatible(final Class<?> clazz) {
|
||||
return this.originClasses == clazz;
|
||||
}
|
||||
|
||||
|
||||
public List<ClassModel> getDependencyModels() {
|
||||
return this.dependencyModels;
|
||||
}
|
||||
|
||||
|
||||
public static ClassModel getModel(final Type type, final ModelGroup previousModel) throws IOException {
|
||||
if (type instanceof final ParameterizedType paramType) {
|
||||
final Type[] typeArguments = paramType.getActualTypeArguments();
|
||||
@ -37,7 +37,7 @@ public abstract class ClassModel {
|
||||
}
|
||||
return previousModel.add((Class<?>) type);
|
||||
}
|
||||
|
||||
|
||||
public static ClassModel getModelBase(
|
||||
final Class<?> clazz,
|
||||
final Type parameterizedType,
|
||||
@ -53,7 +53,7 @@ public abstract class ClassModel {
|
||||
*/
|
||||
return getModel(parameterizedType, previousModel);
|
||||
}
|
||||
|
||||
|
||||
public static ClassModel getModel(final Class<?> type, final ModelGroup previousModel) throws IOException {
|
||||
if (type == List.class) {
|
||||
throw new IOException("Fail to manage parametrized type...");
|
||||
@ -63,9 +63,13 @@ public abstract class ClassModel {
|
||||
}
|
||||
return previousModel.add(type);
|
||||
}
|
||||
|
||||
|
||||
public abstract void analyze(final ModelGroup group) throws Exception;
|
||||
|
||||
|
||||
public abstract Set<ClassModel> getAlls();
|
||||
|
||||
public List<String> getReadOnlyField() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package org.kar.archidata.externalRestApi.model;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -109,6 +113,13 @@ public class ClassObjectModel extends ClassModel {
|
||||
if (this.isPrimitive) {
|
||||
return;
|
||||
}
|
||||
final List<Class<?>> basicClass = List.of(Void.class, void.class, Character.class, char.class, Short.class,
|
||||
short.class, Integer.class, int.class, Long.class, long.class, Float.class, float.class, Double.class,
|
||||
double.class, Date.class, Timestamp.class, LocalDate.class, LocalTime.class);
|
||||
if (basicClass.contains(clazz)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Local generation of class:
|
||||
LOGGER.trace("parse class: '{}'", clazz.getCanonicalName());
|
||||
final List<String> alreadyAdded = new ArrayList<>();
|
||||
@ -137,7 +148,7 @@ public class ClassObjectModel extends ClassModel {
|
||||
this.fields.add(new FieldProperty(elem, previous));
|
||||
}
|
||||
this.name = clazz.getName();
|
||||
|
||||
|
||||
final String[] elems = this.name.split("\\$");
|
||||
if (elems.length == 2) {
|
||||
LOGGER.warn("Can have conflict in generation: {} (Remove class path) ==> {}", this.name, elems[1]);
|
||||
@ -158,4 +169,18 @@ public class ClassObjectModel extends ClassModel {
|
||||
return Set.of(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getReadOnlyField() {
|
||||
final List<String> out = new ArrayList<>();
|
||||
for (final FieldProperty field : this.fields) {
|
||||
if (field.readOnly()) {
|
||||
out.add(field.name);
|
||||
}
|
||||
}
|
||||
if (this.extendsClass != null) {
|
||||
out.addAll(this.extendsClass.getReadOnlyField());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,17 +11,20 @@ import jakarta.ws.rs.core.Response;
|
||||
public class ModelGroup {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(ModelGroup.class);
|
||||
public List<ClassModel> previousModel = new ArrayList<>();
|
||||
|
||||
|
||||
public ModelGroup() {}
|
||||
|
||||
|
||||
public ModelGroup(final List<ClassModel> models) {
|
||||
this.previousModel = models;
|
||||
}
|
||||
|
||||
|
||||
public ClassModel add(Class<?> clazz) {
|
||||
if (clazz == Response.class) {
|
||||
clazz = Object.class;
|
||||
}
|
||||
if (clazz == Number.class) {
|
||||
return null;
|
||||
}
|
||||
//LOGGER.trace("Search element {}", clazz.getCanonicalName());
|
||||
for (final ClassModel value : this.previousModel) {
|
||||
if (value.isCompatible(clazz)) {
|
||||
|
21
src/resources/zod-tools.ts
Normal file
21
src/resources/zod-tools.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2024, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2
|
||||
*/
|
||||
|
||||
import { z as zod, ZodTypeAny, ZodObject } from 'zod';
|
||||
|
||||
export function removeReadonly<T extends ZodTypeAny>(schema: T): T {
|
||||
if (schema instanceof ZodObject) {
|
||||
const shape: Record<string, ZodTypeAny> = {};
|
||||
for (const key in schema.shape) {
|
||||
const field = schema.shape[key];
|
||||
shape[key] = field._def.typeName === 'ZodReadonly'
|
||||
? field._def.innerType
|
||||
: removeReadonly(field);
|
||||
}
|
||||
return zod.object(shape) as T;
|
||||
}
|
||||
return schema;
|
||||
}
|
Loading…
Reference in New Issue
Block a user