[FEAT] model generation is ready
This commit is contained in:
parent
dc022abd2d
commit
9ac3a95060
@ -14,8 +14,18 @@ import org.kar.archidata.externalRestApi.model.ClassMapModel;
|
|||||||
import org.kar.archidata.externalRestApi.model.ClassModel;
|
import org.kar.archidata.externalRestApi.model.ClassModel;
|
||||||
import org.kar.archidata.externalRestApi.model.ClassObjectModel;
|
import org.kar.archidata.externalRestApi.model.ClassObjectModel;
|
||||||
import org.kar.archidata.externalRestApi.model.ClassObjectModel.FieldProperty;
|
import org.kar.archidata.externalRestApi.model.ClassObjectModel.FieldProperty;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class TsClassElement {
|
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 List<ClassModel> models;
|
||||||
public String zodName;
|
public String zodName;
|
||||||
public String tsTypeName;
|
public String tsTypeName;
|
||||||
@ -23,11 +33,10 @@ public class TsClassElement {
|
|||||||
public String declaration;
|
public String declaration;
|
||||||
public String fileName = null;
|
public String fileName = null;
|
||||||
public String comment = null;
|
public String comment = null;
|
||||||
public boolean isEnum = false;
|
public DefinedPosition nativeType = DefinedPosition.NORMAL;
|
||||||
public boolean nativeType;
|
|
||||||
|
|
||||||
public TsClassElement(final List<ClassModel> model, final String zodName, final String tsTypeName,
|
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.models = model;
|
||||||
this.zodName = zodName;
|
this.zodName = zodName;
|
||||||
this.tsTypeName = tsTypeName;
|
this.tsTypeName = tsTypeName;
|
||||||
@ -44,7 +53,6 @@ public class TsClassElement {
|
|||||||
this.tsTypeName = model.getOriginClasses().getSimpleName();
|
this.tsTypeName = model.getOriginClasses().getSimpleName();
|
||||||
this.tsCheckType = "is" + model.getOriginClasses().getSimpleName();
|
this.tsCheckType = "is" + model.getOriginClasses().getSimpleName();
|
||||||
this.declaration = null;
|
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")
|
this.fileName = this.tsTypeName.replaceAll("([a-z])([A-Z])", "$1-$2").replaceAll("([A-Z])([A-Z][a-z])", "$1-$2")
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
}
|
}
|
||||||
@ -58,7 +66,7 @@ public class TsClassElement {
|
|||||||
/**
|
/**
|
||||||
* Interface of the server (auto-generated code)
|
* 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(this.tsTypeName);
|
||||||
out.append(");\n");
|
out.append(");\n");
|
||||||
}
|
}
|
||||||
out.append(generateExportCheckFunction());
|
out.append(generateExportCheckFunctionWrite(""));
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object generateExportCheckFunction() {
|
private String generateExportCheckFunctionWrite(final String writeString) {
|
||||||
final StringBuilder out = new StringBuilder();
|
final StringBuilder out = new StringBuilder();
|
||||||
out.append("\nexport function ");
|
out.append("\nexport function ");
|
||||||
out.append(this.tsCheckType);
|
out.append(this.tsCheckType);
|
||||||
|
out.append(writeString);
|
||||||
out.append("(data: any): data is ");
|
out.append("(data: any): data is ");
|
||||||
out.append(this.tsTypeName);
|
out.append(this.tsTypeName);
|
||||||
|
out.append(writeString);
|
||||||
out.append(" {\n\ttry {\n\t\t");
|
out.append(" {\n\ttry {\n\t\t");
|
||||||
out.append(this.zodName);
|
out.append(this.zodName);
|
||||||
|
out.append(writeString);
|
||||||
out.append("""
|
out.append("""
|
||||||
.parse(data);
|
.parse(data);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,10 +171,10 @@ public class TsClassElement {
|
|||||||
final StringBuilder out = new StringBuilder();
|
final StringBuilder out = new StringBuilder();
|
||||||
for (final ClassModel depModel : depModels) {
|
for (final ClassModel depModel : depModels) {
|
||||||
final TsClassElement tsModel = tsGroup.find(depModel);
|
final TsClassElement tsModel = tsGroup.find(depModel);
|
||||||
if (!tsModel.nativeType) {
|
if (tsModel.nativeType != DefinedPosition.NATIVE) {
|
||||||
out.append("import {");
|
out.append("import {");
|
||||||
out.append(tsModel.zodName);
|
out.append(tsModel.zodName);
|
||||||
out.append("} from \"");
|
out.append("} from \"./");
|
||||||
out.append(tsModel.fileName);
|
out.append(tsModel.fileName);
|
||||||
out.append("\";\n");
|
out.append("\";\n");
|
||||||
}
|
}
|
||||||
@ -193,6 +208,45 @@ public class TsClassElement {
|
|||||||
return out.toString();
|
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 {
|
public String generateObject(final ClassObjectModel model, final TsClassElementGroup tsGroup) throws IOException {
|
||||||
final StringBuilder out = new StringBuilder();
|
final StringBuilder out = new StringBuilder();
|
||||||
out.append(getBaseHeader());
|
out.append(getBaseHeader());
|
||||||
@ -201,7 +255,7 @@ public class TsClassElement {
|
|||||||
|
|
||||||
out.append(generateComment(model));
|
out.append(generateComment(model));
|
||||||
out.append("export const ");
|
out.append("export const ");
|
||||||
out.append(this.tsTypeName);
|
out.append(this.zodName);
|
||||||
out.append(" = ");
|
out.append(" = ");
|
||||||
|
|
||||||
if (model.getExtendsClass() != null) {
|
if (model.getExtendsClass() != null) {
|
||||||
@ -216,10 +270,10 @@ public class TsClassElement {
|
|||||||
for (final FieldProperty field : model.getFields()) {
|
for (final FieldProperty field : model.getFields()) {
|
||||||
final ClassModel fieldModel = field.model();
|
final ClassModel fieldModel = field.model();
|
||||||
if (field.comment() != null) {
|
if (field.comment() != null) {
|
||||||
out.append("\t/*\n");
|
out.append("\t/**\n");
|
||||||
out.append("\t * ");
|
out.append("\t * ");
|
||||||
out.append(field.comment());
|
out.append(field.comment());
|
||||||
out.append("\n\t*/\n");
|
out.append("\n\t */\n");
|
||||||
}
|
}
|
||||||
out.append("\t");
|
out.append("\t");
|
||||||
out.append(field.name());
|
out.append(field.name());
|
||||||
@ -234,15 +288,46 @@ public class TsClassElement {
|
|||||||
final String data = generateTsMap(fieldMapModel, tsGroup);
|
final String data = generateTsMap(fieldMapModel, tsGroup);
|
||||||
out.append(data);
|
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("\n});\n");
|
||||||
out.append("\nexport type ");
|
out.append(generateZodInfer(this.tsTypeName, this.zodName));
|
||||||
out.append(this.tsTypeName);
|
out.append(generateExportCheckFunctionWrite(""));
|
||||||
out.append(" = zod.infer<typeof ");
|
|
||||||
|
// Generate the Write Type associated.
|
||||||
|
out.append("\nexport const ");
|
||||||
out.append(this.zodName);
|
out.append(this.zodName);
|
||||||
|
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");
|
out.append(">;\n");
|
||||||
out.append(generateExportCheckFunction());
|
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,15 +393,16 @@ public class TsClassElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generateFile(final String pathPackage, final TsClassElementGroup tsGroup) throws IOException {
|
public void generateFile(final String pathPackage, final TsClassElementGroup tsGroup) throws IOException {
|
||||||
if (this.nativeType) {
|
if (this.nativeType == DefinedPosition.NATIVE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final ClassModel model = this.models.get(0);
|
final ClassModel model = this.models.get(0);
|
||||||
String data = "";
|
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);
|
data = generateEnum(modelEnum, tsGroup);
|
||||||
}
|
} else if (model instanceof final ClassObjectModel modelObject) {
|
||||||
if (model instanceof final ClassObjectModel modelObject) {
|
|
||||||
data = generateObject(modelObject, tsGroup);
|
data = generateObject(modelObject, tsGroup);
|
||||||
}
|
}
|
||||||
final Path path = Paths.get(pathPackage + File.separator + "model");
|
final Path path = Paths.get(pathPackage + File.separator + "model");
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package org.kar.archidata.externalRestApi;
|
package org.kar.archidata.externalRestApi;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@ -12,6 +16,8 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.kar.archidata.dataAccess.DataFactoryTsApi;
|
||||||
|
import org.kar.archidata.externalRestApi.TsClassElement.DefinedPosition;
|
||||||
import org.kar.archidata.externalRestApi.model.ClassModel;
|
import org.kar.archidata.externalRestApi.model.ClassModel;
|
||||||
|
|
||||||
public class TsGenerateApi {
|
public class TsGenerateApi {
|
||||||
@ -38,6 +44,31 @@ public class TsGenerateApi {
|
|||||||
for (final TsClassElement element : localModel) {
|
for (final TsClassElement element : localModel) {
|
||||||
element.generateFile(pathPackage, tsGroup);
|
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) {
|
private static List<TsClassElement> generateApiModel(final AnalyzeApi api) {
|
||||||
@ -45,72 +76,87 @@ public class TsGenerateApi {
|
|||||||
final List<TsClassElement> tsModels = new ArrayList<>();
|
final List<TsClassElement> tsModels = new ArrayList<>();
|
||||||
List<ClassModel> models = getCompatibleModels(api.classModels, List.of(Void.class, void.class));
|
List<ClassModel> models = getCompatibleModels(api.classModels, List.of(Void.class, void.class));
|
||||||
if (models != null) {
|
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
|
// Map is binded to any ==> can not determine this complex model for now
|
||||||
models = getCompatibleModels(api.classModels, List.of(Map.class));
|
models = getCompatibleModels(api.classModels, List.of(Map.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(String.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(InputStream.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Boolean.class, boolean.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(UUID.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Long.class, long.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Short.class, short.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Integer.class, int.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Double.class, double.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Float.class, float.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Instant.class));
|
||||||
if (models != null) {
|
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));
|
models = getCompatibleModels(api.classModels, List.of(Date.class));
|
||||||
if (models != null) {
|
if (models != null) {
|
||||||
tsModels.add(new TsClassElement(models, "ZodDate", "Date", "isDate",
|
tsModels.add(new TsClassElement(models, "ZodIsoDate", "IsoDate", "isIsoDate",
|
||||||
"zod.string().datetime({ precision: 3 })", false));
|
"zod.string().datetime({ precision: 3 })", DefinedPosition.BASIC));
|
||||||
}
|
}
|
||||||
models = getCompatibleModels(api.classModels, List.of(Timestamp.class));
|
models = getCompatibleModels(api.classModels, List.of(Timestamp.class));
|
||||||
if (models != null) {
|
if (models != null) {
|
||||||
tsModels.add(new TsClassElement(models, "ZodTimestamp", "Timestamp", "isTimestamp",
|
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));
|
models = getCompatibleModels(api.classModels, List.of(LocalDate.class));
|
||||||
if (models != null) {
|
if (models != null) {
|
||||||
tsModels.add(new TsClassElement(models, "ZodLocalDate", "LocalDate", "isLocalDate", "zod.string().date()",
|
tsModels.add(new TsClassElement(models, "ZodLocalDate", "LocalDate", "isLocalDate", "zod.string().date()",
|
||||||
false));
|
DefinedPosition.BASIC));
|
||||||
}
|
}
|
||||||
models = getCompatibleModels(api.classModels, List.of(LocalTime.class));
|
models = getCompatibleModels(api.classModels, List.of(LocalTime.class));
|
||||||
if (models != null) {
|
if (models != null) {
|
||||||
tsModels.add(new TsClassElement(models, "ZodLocalTime", "LocalTime", "isLocalTime", "zod.string().time()",
|
tsModels.add(new TsClassElement(models, "ZodLocalTime", "LocalTime", "isLocalTime", "zod.string().time()",
|
||||||
false));
|
DefinedPosition.BASIC));
|
||||||
}
|
}
|
||||||
for (final ClassModel model : api.classModels) {
|
for (final ClassModel model : api.classModels) {
|
||||||
boolean alreadyExist = false;
|
boolean alreadyExist = false;
|
||||||
@ -126,5 +172,22 @@ public class TsGenerateApi {
|
|||||||
tsModels.add(new TsClassElement(model));
|
tsModels.add(new TsClassElement(model));
|
||||||
}
|
}
|
||||||
return tsModels;
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,4 +68,8 @@ public abstract class ClassModel {
|
|||||||
|
|
||||||
public abstract Set<ClassModel> getAlls();
|
public abstract Set<ClassModel> getAlls();
|
||||||
|
|
||||||
|
public List<String> getReadOnlyField() {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package org.kar.archidata.externalRestApi.model;
|
package org.kar.archidata.externalRestApi.model;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -109,6 +113,13 @@ public class ClassObjectModel extends ClassModel {
|
|||||||
if (this.isPrimitive) {
|
if (this.isPrimitive) {
|
||||||
return;
|
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:
|
// Local generation of class:
|
||||||
LOGGER.trace("parse class: '{}'", clazz.getCanonicalName());
|
LOGGER.trace("parse class: '{}'", clazz.getCanonicalName());
|
||||||
final List<String> alreadyAdded = new ArrayList<>();
|
final List<String> alreadyAdded = new ArrayList<>();
|
||||||
@ -158,4 +169,18 @@ public class ClassObjectModel extends ClassModel {
|
|||||||
return Set.of(this);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,9 @@ public class ModelGroup {
|
|||||||
if (clazz == Response.class) {
|
if (clazz == Response.class) {
|
||||||
clazz = Object.class;
|
clazz = Object.class;
|
||||||
}
|
}
|
||||||
|
if (clazz == Number.class) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
//LOGGER.trace("Search element {}", clazz.getCanonicalName());
|
//LOGGER.trace("Search element {}", clazz.getCanonicalName());
|
||||||
for (final ClassModel value : this.previousModel) {
|
for (final ClassModel value : this.previousModel) {
|
||||||
if (value.isCompatible(clazz)) {
|
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…
x
Reference in New Issue
Block a user