diff --git a/bin/ocaml-client-petstore.sh b/bin/ocaml-client-petstore.sh new file mode 100755 index 00000000000..d124ad74b0a --- /dev/null +++ b/bin/ocaml-client-petstore.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +SCRIPT="$0" +echo "# START SCRIPT: $SCRIPT" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar" + +if [ ! -f "$executable" ] +then + mvn -B clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DdebugOperations -DloggerPath=conf/log4j.properties" + +args="generate -t modules/openapi-generator/src/main/resources/ocaml-client -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g ocaml-client -o samples/client/petstore/ocaml-client --additional-properties packageName=petstore_client $@" + +echo "java ${JAVA_OPTS} -jar ${executable} ${args}" +java $JAVA_OPTS -jar $executable $args diff --git a/bin/openapi3/ocaml-client-petstore.sh b/bin/openapi3/ocaml-client-petstore.sh new file mode 100755 index 00000000000..7c9aeb7c55a --- /dev/null +++ b/bin/openapi3/ocaml-client-petstore.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +SCRIPT="$0" +echo "# START SCRIPT: $SCRIPT" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar" + +if [ ! -f "$executable" ] +then + mvn -B clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DdebugOperations -DloggerPath=conf/log4j.properties" + +args="generate -t modules/openapi-generator/src/main/resources/ocaml-client -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ocaml-client -o samples/openapi3/client/petstore/ocaml-client/ --additional-properties packageName=petstore_client $@" + +echo "java ${JAVA_OPTS} -jar ${executable} ${args}" +java $JAVA_OPTS -jar $executable $args diff --git a/docs/generators.md b/docs/generators.md index ecb4edfd40c..12c7ecdfedc 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -39,6 +39,7 @@ The following generators are available: - [kotlin](generators/kotlin.md) - [lua](generators/lua.md) - [objc](generators/objc.md) + - [ocaml-client](generators/ocaml-client.md) - [perl](generators/perl.md) - [php](generators/php.md) - [powershell](generators/powershell.md) diff --git a/docs/generators/ocaml-client.md b/docs/generators/ocaml-client.md new file mode 100644 index 00000000000..52874232c1e --- /dev/null +++ b/docs/generators/ocaml-client.md @@ -0,0 +1,13 @@ + +--- +id: generator-opts-client-ocaml-client +title: Config Options for ocaml-client +sidebar_label: ocaml-client +--- + +| Option | Description | Values | Default | +| ------ | ----------- | ------ | ------- | +|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true| +|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false| +|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java new file mode 100644 index 00000000000..5df13a046b1 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java @@ -0,0 +1,728 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.languages; + +import com.google.common.base.Strings; +import io.swagger.v3.oas.models.*; +import io.swagger.v3.oas.models.media.*; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.responses.ApiResponse; +import org.openapitools.codegen.*; +import org.openapitools.codegen.utils.ModelUtils; +import org.openapitools.codegen.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; +import java.util.stream.Collectors; + +import static org.apache.commons.lang3.StringUtils.capitalize; +import static org.openapitools.codegen.utils.StringUtils.underscore; + +public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(OCamlClientCodegen.class); + public static final String PACKAGE_NAME = "packageName"; + public static final String PACKAGE_VERSION = "packageVersion"; + + static final String X_MODEL_MODULE = "x-modelModule"; + + public static final String CO_HTTP = "cohttp"; + + protected String packageName = "openapi"; + protected String packageVersion = "1.0.0"; + protected String apiDocPath = "docs/"; + protected String modelDocPath = "docs/"; + protected String apiFolder = "src/apis"; + protected String modelFolder = "src/models"; + + private Map> enumNames = new HashMap<>(); + private Map enumHash = new HashMap<>(); + private Map enumUniqNames; + + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + public String getName() { + return "ocaml-client"; + } + + public String getHelp() { + return "Generates an OCaml client library (beta)."; + } + + public OCamlClientCodegen() { + super(); + outputFolder = "generated-code/ocaml-client"; + modelTemplateFiles.put("model.mustache", ".ml"); + + // default HIDE_GENERATION_TIMESTAMP to true + hideGenerationTimestamp = Boolean.TRUE; + + embeddedTemplateDir = templateDir = "ocaml-client"; + + setReservedWordsLowerCase( + Arrays.asList( + "and", "as", "assert", "asr", "begin", "class", + "constraint", "do", "done", "downto", "else", "end", + "exception", "external", "false", "for ", "fun", "function", + "functor", "if", "in", "include", "inherit", "initializer", + "land", "lazy", "let", "lor", "lsl", "lsr", + "lxor", "match", "method", "mod", "module", "mutable", + "new", "nonrec", "object", "of", "open", "or", + "private", "rec", "sig", "struct", "then", "to", + "true", "try", "type", "val", "virtual", "when", + "while", "with" + ) + ); + + importMapping.remove("File"); + + supportingFiles.add(new SupportingFile("dune.mustache", "", "dune")); + supportingFiles.add(new SupportingFile("dune-project.mustache", "", "dune-project")); + + defaultIncludes = new HashSet<>( + Arrays.asList( + "int", + "int32", + "int64", + "float", + "bool", + "char", + "string", + "list" + ) + ); + + languageSpecificPrimitives = new HashSet<>( + Arrays.asList( + "int", + "int32", + "int64", + "float", + "bool", + "char", + "string", + "bytes", + "list", + "Yojson.Safe.t" + ) + ); + + instantiationTypes.clear(); + + typeMapping.clear(); + typeMapping.put("boolean", "bool"); + typeMapping.put("int", "int32"); + typeMapping.put("long", "int64"); + typeMapping.put("short", "int"); + typeMapping.put("char", "char"); + typeMapping.put("float", "float"); + typeMapping.put("double", "float"); + typeMapping.put("integer", "int32"); + typeMapping.put("number", "float"); + typeMapping.put("date", "string"); + typeMapping.put("object", "Yojson.Safe.t"); + typeMapping.put("any", "Yojson.Safe.t"); + typeMapping.put("file", "string"); + typeMapping.put("ByteArray", "bytes"); + // lib + typeMapping.put("string", "string"); + typeMapping.put("UUID", "string"); + typeMapping.put("URI", "string"); + typeMapping.put("set", "`Set"); + typeMapping.put("passsword", "string"); + typeMapping.put("DateTime", "string"); + +// supportedLibraries.put(CO_HTTP, "HTTP client: CoHttp."); +// +// CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use."); +// libraryOption.setEnum(supportedLibraries); +// // set hyper as the default +// libraryOption.setDefault(CO_HTTP); +// cliOptions.add(libraryOption); +// setLibrary(CO_HTTP); + } + + @Override + public Map postProcessAllModels(Map superobjs) { + List toRemove = new ArrayList<>(); + + for (Map.Entry modelEntry : superobjs.entrySet()) { + Map objs = (Map) modelEntry.getValue(); + // process enum in models + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + toRemove.add(modelEntry.getKey()); + } else { + enrichPropertiesWithEnumDefaultValues(cm.getAllVars()); + enrichPropertiesWithEnumDefaultValues(cm.getReadOnlyVars()); + enrichPropertiesWithEnumDefaultValues(cm.getReadWriteVars()); + enrichPropertiesWithEnumDefaultValues(cm.getRequiredVars()); + enrichPropertiesWithEnumDefaultValues(cm.getOptionalVars()); + enrichPropertiesWithEnumDefaultValues(cm.getVars()); + enrichPropertiesWithEnumDefaultValues(cm.getParentVars()); + } + } + } + + for (String keyToRemove : toRemove) { + superobjs.remove(keyToRemove); + } + + return superobjs; + + } + + private void enrichPropertiesWithEnumDefaultValues(List properties) { + for (CodegenProperty property : properties) { + if (property.get_enum() != null && property.get_enum().size() == 1) { + String value = property.get_enum().get(0); + property.defaultValue = ocamlizeEnumValue(value); + } + } + } + + @Override + protected void updateDataTypeWithEnumForMap(CodegenProperty property) { + CodegenProperty baseItem = property.items; + while (baseItem != null && (Boolean.TRUE.equals(baseItem.isMapContainer) + || Boolean.TRUE.equals(baseItem.isListContainer))) { + baseItem = baseItem.items; + } + + if (baseItem != null) { + // set default value for variable with inner enum + if (property.defaultValue != null) { + property.defaultValue = property.defaultValue.replace(", " + property.items.baseType, ", " + toEnumName(property.items)); + } + + updateCodegenPropertyEnum(property); + } + } + + @Override + protected void updateDataTypeWithEnumForArray(CodegenProperty property) { + CodegenProperty baseItem = property.items; + while (baseItem != null && (Boolean.TRUE.equals(baseItem.isMapContainer) + || Boolean.TRUE.equals(baseItem.isListContainer))) { + baseItem = baseItem.items; + } + if (baseItem != null) { + // set default value for variable with inner enum + if (property.defaultValue != null) { + property.defaultValue = property.defaultValue.replace(baseItem.baseType, toEnumName(baseItem)); + } + + updateCodegenPropertyEnum(property); + } + } + + @SuppressWarnings("unchecked") + private String hashEnum(Schema schema) { + return ((List) schema.getEnum()).stream().map(String::valueOf).collect(Collectors.joining(",")); + } + + private boolean isEnumSchema(Schema schema) { + return schema != null && schema.getEnum() != null && !schema.getEnum().isEmpty(); + } + + private void collectEnumSchemas(String parentName, String sName, Schema schema) { + if (schema instanceof ArraySchema) { + collectEnumSchemas(parentName, sName, ((ArraySchema)schema).getItems()); + } else if (schema instanceof MapSchema && schema.getAdditionalProperties() instanceof Schema) { + collectEnumSchemas(parentName, sName, (Schema) schema.getAdditionalProperties()); + } else if (isEnumSchema(schema)) { + String h = hashEnum(schema); + if (!enumHash.containsKey(h)) { + enumHash.put(h, schema); + enumNames.computeIfAbsent(h, k -> new ArrayList<>()).add(sName.toLowerCase(Locale.ROOT)); + if (parentName != null) { + enumNames.get(h).add((parentName + "_" + sName).toLowerCase(Locale.ROOT)); + } + } + } + } + + private void collectEnumSchemas(String sName, Schema schema) { + collectEnumSchemas(null, sName, schema); + } + + @SuppressWarnings("unchecked") + private void collectEnumSchemas(String parentName, Map schemas) { + for (String sName : schemas.keySet()) { + Schema schema = schemas.get(sName); + + collectEnumSchemas(parentName, sName, schema); + + if (schema.getProperties() != null) { + String pName = parentName != null ? parentName + "_" + sName : sName; + collectEnumSchemas(pName, schema.getProperties()); + } + + if (schema.getAdditionalProperties() != null && schema.getAdditionalProperties() instanceof Schema) { + String pName = parentName != null ? parentName + "_" + sName : sName; + collectEnumSchemas(pName, (Schema) schema.getAdditionalProperties()); + } + + if (schema instanceof ArraySchema) { + ArraySchema s = (ArraySchema) schema; + if (s.getItems() != null) { + String pName = parentName != null ? parentName + "_" + sName : sName; + collectEnumSchemas(pName, s.getItems()); + } + } + } + } + + private void collectEnumSchemas(Operation operation) { + if (operation != null) { + if (operation.getParameters() != null) { + for (Parameter parameter : operation.getParameters()) { + collectEnumSchemas(parameter.getName(), parameter.getSchema()); + } + } + if (operation.getRequestBody() != null && operation.getRequestBody().getContent() != null) { + Content content = operation.getRequestBody().getContent(); + for (String p : content.keySet()) { + collectEnumSchemas(p, content.get(p).getSchema()); + } + } + if (operation.getResponses() != null) { + for (String s : operation.getResponses().keySet()) { + ApiResponse apiResponse = operation.getResponses().get(s); + if (apiResponse.getContent() != null) { + Content content = apiResponse.getContent(); + for (String p : content.keySet()) { + collectEnumSchemas(p, content.get(p).getSchema()); + } + } + } + } + } + } + + private String sanitizeOCamlTypeName(String name) { + String typeName = name.replace("-", "_").replace(" ", "_").trim(); + int i = 0; + char c; + while (i < typeName.length() && (Character.isDigit(c = typeName.charAt(i)) || c == '_')) { + i++; + } + + return typeName.substring(i); + } + + private void computeEnumUniqNames() { + Map definitiveNames = new HashMap<>(); + for (String h : enumNames.keySet()) { + boolean hasDefName = false; + List nameCandidates = enumNames.get(h); + for (String name : nameCandidates) { + String candidate = sanitizeOCamlTypeName(name); + if (!definitiveNames.containsKey(candidate) && !reservedWords.contains(candidate)) { + definitiveNames.put(candidate, h); + hasDefName = true; + break; + } + } + if (!hasDefName) { + int i = 0; + String candidate;; + while (definitiveNames.containsKey(candidate = sanitizeOCamlTypeName(nameCandidates.get(0) + "_" + i))) { + i++; + } + definitiveNames.put(candidate, h); + } + } + + enumUniqNames = definitiveNames.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + } + + private void collectEnumSchemas(OpenAPI openAPI) { + Components components = openAPI.getComponents(); + if (components != null && components.getSchemas() != null && !components.getSchemas().isEmpty()) { + collectEnumSchemas(null, components.getSchemas()); + } + + Paths paths = openAPI.getPaths(); + if (paths != null && !paths.isEmpty()) { + for (String path : paths.keySet()) { + PathItem item = paths.get(path); + collectEnumSchemas(item.getGet()); + collectEnumSchemas(item.getPost()); + collectEnumSchemas(item.getPut()); + collectEnumSchemas(item.getDelete()); + collectEnumSchemas(item.getPatch()); + collectEnumSchemas(item.getOptions()); + collectEnumSchemas(item.getHead()); + collectEnumSchemas(item.getTrace()); + } + } + + computeEnumUniqNames(); + } + + @Override + public void preprocessOpenAPI(OpenAPI openAPI) { + collectEnumSchemas(openAPI); + + supportingFiles.add(new SupportingFile("lib.mustache", "", packageName + ".opam")); + supportingFiles.add(new SupportingFile("support.mustache", "src/support", "request.ml")); + supportingFiles.add(new SupportingFile("json.mustache", "src/support", "jsonSupport.ml")); + supportingFiles.add(new SupportingFile("enums.mustache", "src/support", "enums.ml")); + } + + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) { + setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME)); + } else { + setPackageName("openapi"); + } + + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) { + setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION)); + } else { + setPackageVersion("1.0.0"); + } + + additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName); + additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion); + + additionalProperties.put("apiDocPath", apiDocPath); + additionalProperties.put("modelDocPath", modelDocPath); + + apiTemplateFiles.put("api-impl.mustache", ".ml"); + apiTemplateFiles.put("api-intf.mustache", ".mli"); + + modelPackage = packageName; + apiPackage = packageName; + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return '_' + name; + } + + @Override + public String apiFileFolder() { + return (outputFolder + File.separator + apiFolder).replace("/", File.separator); + } + + @Override + public String modelFileFolder() { + return (outputFolder + File.separator + modelFolder).replace("/", File.separator); + } + + @Override + public String toVarName(String name) { + // replace - with _ e.g. created-at => created_at + name = sanitizeName(name.replaceAll("-", "_")); + + // snake_case, e.g. PetId => pet_id + name = underscore(name); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name)) + name = escapeReservedWord(name); + + // for reserved word or word starting with number, append _ + if (name.matches("^\\d.*")) + name = "var_" + name; + + return name; + } + + @Override + public String toParamName(String name) { + return toVarName(name); + } + + @Override + public String toModelName(String name) { + // camelize the model name + // phone_number => PhoneNumber + return capitalize(toModelFilename(name)) + ".t"; + } + + @Override + public String toModelFilename(String name) { + + if (!Strings.isNullOrEmpty(modelNamePrefix)) { + name = modelNamePrefix + "_" + name; + } + + if (!Strings.isNullOrEmpty(modelNameSuffix)) { + name = name + "_" + modelNameSuffix; + } + + name = sanitizeName(name); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(name)) { + LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + ("model_" + name)); + name = "model_" + name; // e.g. return => ModelReturn (after camelize) + } + + // model name starts with number or _ + if (name.matches("^\\d.*|^_.*")) { + LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + ("model_" + name)); + name = "model_" + name; // e.g. 200Response => Model200Response (after camelize) + } + + return underscore(name); + } + + @Override + public String toApiFilename(final String name) { + // replace - with _ e.g. created-at => created_at + final String _name = name.replaceAll("-", "_"); + + // e.g. PetApi.ml => pet_api.ml + return underscore(_name) + "_api"; + } + + @Override + public String apiDocFileFolder() { + return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar); + } + + @Override + public String modelDocFileFolder() { + return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar); + } + + @Override + public String toModelDocFilename(String name) { + return toModelName(name); + } + + @Override + public String toApiDocFilename(String name) { + return toApiName(name); + } + + @Override + public String getTypeDeclaration(Schema p) { + if (ModelUtils.isArraySchema(p)) { + ArraySchema ap = (ArraySchema) p; + Schema inner = ap.getItems(); + if (inner == null) { + LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined.Default to string"); + inner = new StringSchema().description("TODO default missing array inner type to string"); + } + return getTypeDeclaration(inner) + " list"; + } else if (ModelUtils.isMapSchema(p)) { + Schema inner = ModelUtils.getAdditionalProperties(p); + if (inner == null) { + LOGGER.warn(p.getName() + "(map property) does not have a proper inner type defined. Default to string"); + inner = new StringSchema().description("TODO default missing map inner type to string"); + } + String prefix = inner.getEnum() != null ? "Enums." : ""; + return "(string * " + prefix + getTypeDeclaration(inner) + ") list"; + } else if (p.getEnum() != null) { + String h = hashEnum(p); + return enumUniqNames.get(h); + } + + Schema referencedSchema = ModelUtils.getReferencedSchema(openAPI, p); + if (referencedSchema != null && referencedSchema.getEnum() != null) { + String h = hashEnum(referencedSchema); + return "Enums." + enumUniqNames.get(h); + } + + // Not using the supertype invocation, because we want to UpperCamelize + // the type. + String schemaType = getSchemaType(p); + if (typeMapping.containsKey(schemaType)) { + return typeMapping.get(schemaType); + } + + if (typeMapping.containsValue(schemaType)) { + return schemaType; + } + + if (languageSpecificPrimitives.contains(schemaType)) { + return schemaType; + } + + return toModelName(schemaType); + } + + @Override + public String getSchemaType(Schema p) { + String schemaType = super.getSchemaType(p); + if (typeMapping.containsKey(schemaType)) { + String type = typeMapping.get(schemaType); + if (languageSpecificPrimitives.contains(type)) { + return type; + } + } + return capitalize(toModelFilename(schemaType)); + } + + @Override + public String toOperationId(String operationId) { + String sanitizedOperationId = sanitizeName(operationId); + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(sanitizedOperationId) || sanitizedOperationId.matches("^[0-9].*")) { + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + StringUtils.underscore("call_" + operationId)); + sanitizedOperationId = "call_" + sanitizedOperationId; + } + + return StringUtils.underscore(sanitizedOperationId); + } + + private Map allowableValues(String valueString) { + Map result = new HashMap<>(); + result.put("values", buildEnumValues(valueString)); + return result; + } + + private List> buildEnumValues(String valueString) { + List> result = new ArrayList<>(); + + for (String v : valueString.split(",")) { + Map m = new HashMap<>(); + String value = v.isEmpty() ? "empty" : v; + m.put("name", value); + m.put("camlEnumValueName", ocamlizeEnumValue(value)); + result.add(m); + } + + return result; + } + + private String ocamlizeEnumValue(String value) { + String sanitizedValue = + super.toVarName(value.isEmpty() ? "empty" : value) + .replace(" ", "_"); + + if (!sanitizedValue.matches("^[a-zA-Z_].*")) { + sanitizedValue = "_" + sanitizedValue; + } + return "`" + capitalize(sanitizedValue); + } + + private CodegenModel buildEnumModel(String enumName, String values) { + CodegenModel m = new CodegenModel(); + m.setAllowableValues(allowableValues(values)); + m.setName(enumName); + m.setClassname(enumName); + m.setDataType(enumName); + String[] vals = values.split(","); + if (vals.length == 1) { + m.setDefaultValue(ocamlizeEnumValue(vals[0])); + } + m.isEnum = true; + + return m; + } + + private Map buildEnumModelWrapper(String enumName, String values) { + Map m = new HashMap<>(); + m.put("importPath", packageName + "." + enumName); + m.put("model", buildEnumModel(enumName, values)); + return m; + } + + @Override + public Map postProcessOperationsWithModels(Map objs, List allModels) { + @SuppressWarnings("unchecked") + Map objectMap = (Map) objs.get("operations"); + @SuppressWarnings("unchecked") + List operations = (List) objectMap.get("operation"); + for (CodegenOperation operation : operations) { + // http method verb conversion, depending on client library (e.g. Hyper: PUT => Put, Reqwest: PUT => put) + //if (CO_HTTP.equals(getLibrary())) { + for (CodegenParameter param : operation.bodyParams) { + if (param.isModel && param.dataType.endsWith(".t")) { + param.vendorExtensions.put(X_MODEL_MODULE, param.dataType.substring(0, param.dataType.lastIndexOf('.'))); + } + } + } + + for (Map.Entry e : enumUniqNames.entrySet()) { + allModels.add(buildEnumModelWrapper(e.getValue(), e.getKey())); + } + + enumUniqNames.clear(); + + return objs; + } + + @Override + protected boolean needToImport(String type) { + return !defaultIncludes.contains(type) + && !languageSpecificPrimitives.contains(type); + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public void setPackageVersion(String packageVersion) { + this.packageVersion = packageVersion; + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input + .replace("*)", "*_)") + .replace("(*", "(_*") + .replace("\"", "\\\""); + } + + @Override + public String toEnumName(CodegenProperty property) { + String hash = String.join(",", property.get_enum()); + + if (enumUniqNames.containsKey(hash)) { + return enumUniqNames.get(hash); + } + + throw new IllegalArgumentException("Unreferenced enum " + hash); + } + + @Override + public String toDefaultValue(Schema p) { + if (p.getDefault() != null) { + return p.getDefault().toString(); + } else { + return null; + } + } +} diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index ac693c68c87..a27cc518fdc 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -62,6 +62,7 @@ org.openapitools.codegen.languages.LuaClientCodegen org.openapitools.codegen.languages.MysqlSchemaCodegen org.openapitools.codegen.languages.NodeJSServerCodegen org.openapitools.codegen.languages.ObjcClientCodegen +org.openapitools.codegen.languages.OCamlClientCodegen org.openapitools.codegen.languages.OpenAPIGenerator org.openapitools.codegen.languages.OpenAPIYamlGenerator org.openapitools.codegen.languages.PerlClientCodegen diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/api-impl.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/api-impl.mustache new file mode 100644 index 00000000000..5b9e498eb5f --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/api-impl.mustache @@ -0,0 +1,30 @@ +{{>partial_header}} +{{#operations}} +{{#operation}} +{{#description}} + * Schema {{{classname}}} : {{{description}}} +{{/description}} +{{/operation}} +{{/operations}} + *) + +{{#operations}} +{{#operation}} +let {{{operationId}}} {{^hasParams}}(){{/hasParams}}{{#allParams}}{{{paramName}}}{{#hasMore}} {{/hasMore}}{{/allParams}} = + let open Lwt in + let uri = Request.build_uri "{{{path}}}" in + let headers = Request.default_headers in{{#headerParams}} + let headers = Cohttp.Header.add{{#isContainer}}_multi{{/isContainer}} headers "{{baseName}}" ({{> to_string}}{{paramName}}) in{{/headerParams}}{{#pathParams}} + let uri = Request.replace_path_param uri "{{{baseName}}}" ({{> to_string}}{{{paramName}}}) in{{/pathParams}}{{#queryParams}} + let uri = Uri.add_query_param{{^isListContainer}}'{{/isListContainer}} uri ("{{{baseName}}}", {{> to_string}}{{{paramName}}}) in{{/queryParams}}{{#hasAuthMethods}}{{#authMethods}}{{#isApiKey}}{{#isKeyInQuery}} + let uri = Uri.add_query_param' uri ("{{{keyParamName}}}", Request.api_key) in{{/isKeyInQuery}}{{/isApiKey}}{{/authMethods}}{{/hasAuthMethods}}{{#bodyParams}} + let body = Request.write_json_body {{> to_json}} {{{paramName}}} in{{/bodyParams}}{{^hasBodyParam}}{{#hasFormParams}} + let body = Request.init_form_encoded_body () in{{/hasFormParams}}{{#formParams}} + let body = Request.add_form_encoded_body_param{{#isContainer}}s{{/isContainer}} body ("{{{paramName}}}", {{> to_string}}{{{paramName}}}) in{{/formParams}}{{#hasFormParams}} + let body = Request.finalize_form_encoded_body body in{{/hasFormParams}}{{/hasBodyParam}} + Cohttp_lwt_unix.Client.call `{{{httpMethod}}} uri ~headers {{#hasBodyParam}}~body {{/hasBodyParam}}{{^hasBodyParam}}{{#hasFormParams}}~body {{/hasFormParams}}{{/hasBodyParam}}>>= fun (resp, body) ->{{^returnType}} + Request.handle_unit_response resp{{/returnType}}{{#returnType}} + Request.read_json_body{{#returnContainer}}{{#isListContainer}}_as_list{{/isListContainer}}{{#isMapContainer}}_as_map{{/isMapContainer}}{{#returnBaseType}}_of{{/returnBaseType}}{{/returnContainer}}{{^returnContainer}}{{#returnBaseType}}_as{{/returnBaseType}}{{/returnContainer}} {{#returnType}}({{> of_json}}){{/returnType}} resp body{{/returnType}} + +{{/operation}} +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/api-intf.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/api-intf.mustache new file mode 100644 index 00000000000..8bd8de3a4e6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/api-intf.mustache @@ -0,0 +1,15 @@ +{{>partial_header}} +{{#operations}} +{{#operation}} +{{#description}} + * Schema {{{classname}}} : {{{description}}} +{{/description}} +{{/operation}} +{{/operations}} + *) + +{{#operations}} +{{#operation}} +val {{{operationId}}} : {{^hasParams}}unit{{/hasParams}}{{#allParams}}{{#isEnum}}Enums.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#hasMore}} -> {{/hasMore}}{{/allParams}} -> {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}unit{{/returnType}} Lwt.t +{{/operation}} +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/dune-project.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/dune-project.mustache new file mode 100644 index 00000000000..8e48d839f68 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/dune-project.mustache @@ -0,0 +1,2 @@ +(lang dune 1.10) +(name {{{packageName}}}) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/dune.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/dune.mustache new file mode 100644 index 00000000000..e7a9352401d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/dune.mustache @@ -0,0 +1,9 @@ +(include_subdirs unqualified) +(library + (name {{{packageName}}}) + (public_name {{{packageName}}}) + (flags (:standard -w -27)) + (libraries str cohttp-lwt-unix lwt yojson ppx_deriving_yojson.runtime) + (preprocess (pps ppx_deriving_yojson ppx_deriving.std)) + (wrapped true) +) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/enums.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/enums.mustache new file mode 100644 index 00000000000..a9aed87db27 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/enums.mustache @@ -0,0 +1,25 @@ +{{>partial_header}} +{{#description}} + * Schema {{{classname}}} : {{{description}}} +{{/description}} + *) +{{#models}} +{{#model}} +{{#isEnum}} + +type {{name}} = [ +{{#allowableValues}} +{{#values}} +| {{{camlEnumValueName}}} [@printer fun fmt _ -> Format.pp_print_string fmt "{{{name}}}"] [@name "{{{name}}}"] +{{/values}} +{{/allowableValues}} +] [@@deriving yojson, show { with_path = false }];; + +let {{name}}_of_yojson json = {{name}}_of_yojson (`List [json]) +let {{name}}_to_yojson e = + match {{name}}_to_yojson e with + | `List [json] -> json + | json -> json +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/json.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/json.mustache new file mode 100644 index 00000000000..4b0fac77545 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/json.mustache @@ -0,0 +1,55 @@ +open Ppx_deriving_yojson_runtime + +let unwrap to_json json = + match to_json json with + | Result.Ok json -> json + | Result.Error s -> failwith s + +let to_int json = + match json with + | `Int x -> x + | `Intlit s -> int_of_string s + | _ -> failwith "JsonSupport.to_int" + +let to_bool json = + match json with + | `Bool x -> x + | _ -> failwith "JsonSupport.to_bool" + +let to_float json = + match json with + | `Float x -> x + | _ -> failwith "JsonSupport.to_float" + +let to_string json = + match json with + | `String s -> s + | _ -> failwith "JsonSupport.to_string" + +let to_int32 json : int32 = + match json with + | `Int x -> Int32.of_int x + | `Intlit s -> Int32.of_string s + | _ -> failwith "JsonSupport.to_int32" + +let to_int64 json : int64 = + match json with + | `Int x -> Int64.of_int x + | `Intlit s -> Int64.of_string s + | _ -> failwith "JsonSupport.to_int64" + +let of_int x = `Int x + +let of_bool b = `Bool b + +let of_float x = `Float x + +let of_string s = `String s + +let of_int32 x = `Intlit (Int32.to_string x) + +let of_int64 x = `Intlit (Int64.to_string x) + +let of_list_of of_f l = `List (List.map of_f l) + +let of_map_of of_f l = `Assoc (List.map (fun (k, v) -> (k, of_f v)) l) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/lib.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/lib.mustache new file mode 100644 index 00000000000..627f3227880 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/lib.mustache @@ -0,0 +1,15 @@ +opam-version: "2.0" +name: "{{{packageName}}}" +version: "{{{packageVersion}}}" +synopsis: "{{{packageDescription}}}" +description: """ +Longer description +""" +maintainer: "Name " +authors: "Name " +license: "" +homepage: "" +bug-reports: "" +dev-repo: "" +depends: [ "ocaml" "ocamlfind" ] +build: ["dune" "build" "-p" name] \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/model.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/model.mustache new file mode 100644 index 00000000000..33fc27af079 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/model.mustache @@ -0,0 +1,38 @@ +{{>partial_header}} +{{#models}} +{{#model}} +{{#description}} + * Schema {{{classname}}} : {{{description}}} + *) +{{/description}} +{{^description}} + *) +{{/description}} + +{{^isEnum}} +type t = { +{{#vars}} + {{#description}} + (* {{{description}}} *) + {{/description}} + {{#isEnum}} + {{{name}}}: {{^isMapContainer}}Enums.{{/isMapContainer}}{{{datatypeWithEnum}}}{{^isContainer}}{{#defaultValue}}[@default {{{defaultValue}}}]{{/defaultValue}}{{/isContainer}}{{^isContainer}}{{#required}}{{#isNullable}} option [@default None]{{/isNullable}}{{/required}}{{/isContainer}}{{^isContainer}}{{^required}} option [@default None]{{/required}}{{/isContainer}}; + {{/isEnum}} + {{^isEnum}} + {{{name}}}: {{{datatypeWithEnum}}}{{^isContainer}}{{#required}}{{#isNullable}} option{{/isNullable}}{{/required}}{{/isContainer}}{{^isContainer}}{{^required}} option [@default None]{{/required}}{{/isContainer}}; + {{/isEnum}} +{{/vars}} +} [@@deriving yojson, show ];; + +{{#description}} +(** {{{description}}} *) +{{/description}} +let create {{#requiredVars}}({{{name}}} : {{#isEnum}}Enums.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}option{{/isNullable}}){{^-last}} {{/-last}}{{/requiredVars}}{{^hasRequired}}(){{/hasRequired}} : t = { + {{#vars}} + {{{name}}} = {{#required}}{{{name}}}{{/required}}{{^required}}{{#isContainer}}[]{{/isContainer}}{{^isContainer}}None{{/isContainer}}{{/required}}; + {{/vars}} +} +{{/isEnum}} + +{{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/of_json.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/of_json.mustache new file mode 100644 index 00000000000..a7be3d4d7ca --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/of_json.mustache @@ -0,0 +1 @@ +{{#isEnum}}JsonSupport.unwrap Enums.{{{datatypeWithEnum}}}_of_yojson{{/isEnum}}{{^isEnum}}{{#returnType}}{{#returnTypeIsPrimitive}}JsonSupport.to_{{{returnBaseType}}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{#vendorExtensions.x-modelModule}}JsonSupport.unwrap {{{vendorExtensions.x-modelModule}}}.of_yojson{{/vendorExtensions.x-modelModule}}{{^vendorExtensions.x-modelModule}}JsonSupport.unwrap {{{returnBaseType}}}.of_yojson{{/vendorExtensions.x-modelModule}}{{/returnTypeIsPrimitive}}{{/returnType}}{{/isEnum}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/partial_header.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/partial_header.mustache new file mode 100644 index 00000000000..c4bbcd913c4 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/partial_header.mustache @@ -0,0 +1,5 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/support.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/support.mustache new file mode 100644 index 00000000000..e0c33b4f58a --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/support.mustache @@ -0,0 +1,48 @@ +let api_key = "" +let base_url = "{{{basePath}}}" +let default_headers = Cohttp.Header.init_with "Content-Type" "application/json" + +let build_uri operation_path = Uri.of_string (base_url ^ operation_path) +let write_json_body to_json payload = + to_json payload |> Yojson.Safe.to_string ~std:true |> Cohttp_lwt.Body.of_string + +let handle_response resp on_success_handler = + match Cohttp_lwt.Response.status resp with + | #Cohttp.Code.success_status -> on_success_handler () + | s -> failwith ("Server responded with status " ^ Cohttp.Code.(reason_phrase_of_code (code_of_status s))) + +let handle_unit_response resp = handle_response resp (fun () -> Lwt.return ()) + +let read_json_body resp body = + handle_response resp (fun () -> + (Lwt.(Cohttp_lwt.Body.to_string body >|= Yojson.Safe.from_string))) + +let read_json_body_as of_json resp body = + Lwt.(read_json_body resp body >|= of_json) + +let read_json_body_as_list resp body = + Lwt.(read_json_body resp body >|= Yojson.Safe.Util.to_list) + +let read_json_body_as_list_of of_json resp body = + Lwt.(read_json_body_as_list resp body >|= List.map of_json) + +let read_json_body_as_map_of of_json resp body = + Lwt.(read_json_body resp body >|= Yojson.Safe.Util.to_assoc >|= List.map (fun (s, v) -> (s, of_json v))) + +let replace_path_param uri param_name param_value = + let regexp = Str.regexp (Str.quote ("{" ^ param_name ^ "}")) in + let path = Str.global_replace regexp param_value (Uri.path uri) in + Uri.with_path uri path + +let init_form_encoded_body () = "" + +let add_form_encoded_body_param params (paramName, paramValue) = + let new_param_enc = Printf.sprintf {|%s=%s|} (Uri.pct_encode paramName) (Uri.pct_encode paramValue) in + if params = "" + then new_param_enc + else Printf.sprintf {|%s&%s|} params new_param_enc + +let add_form_encoded_body_params params (paramName, new_params) = + add_form_encoded_body_param params (paramName, String.concat "," new_params) + +let finalize_form_encoded_body body = Cohttp_lwt.Body.of_string body diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/to_json.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/to_json.mustache new file mode 100644 index 00000000000..6b8fea90fdc --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/to_json.mustache @@ -0,0 +1 @@ +{{#isListContainer}}{{#items}}(JsonSupport.of_list_of {{> to_json}}){{/items}}{{/isListContainer}}{{#isMapContainer}}{{#items}}(JsonSupport.of_map_of {{> to_json}}){{/items}}{{/isMapContainer}}{{#isString}}JsonSupport.of_string{{/isString}}{{#isLong}}JsonSupport.of_int64{{/isLong}}{{#isInteger}}JsonSupport.of_int32{{/isInteger}}{{#isFloat}}JsonSupport.of_float{{/isFloat}}{{#isNumber}}JsonSupport.of_float{{/isNumber}}{{#isDouble}}JsonSupport.of_float{{/isDouble}}{{#isBoolean}}JsonSupport.of_bool{{/isBoolean}}{{^isEnum}}{{#isModel}}{{#vendorExtensions.x-modelModule}}{{{vendorExtensions.x-modelModule}}}.to_yojson{{/vendorExtensions.x-modelModule}}{{^vendorExtensions.x-modelModule}}{{{baseType}}}.to_yojson{{/vendorExtensions.x-modelModule}}{{/isModel}}{{/isEnum}}{{^isModel}}{{^isContainer}}{{#isEnum}}Enums.{{{datatypeWithEnum}}}_to_yojson{{/isEnum}}{{/isContainer}}{{/isModel}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ocaml-client/to_string.mustache b/modules/openapi-generator/src/main/resources/ocaml-client/to_string.mustache new file mode 100644 index 00000000000..b7be4f380df --- /dev/null +++ b/modules/openapi-generator/src/main/resources/ocaml-client/to_string.mustache @@ -0,0 +1 @@ +{{#isContainer}}{{#items}}{{#isEnum}}List.map {{> to_string}}{{/isEnum}}{{#isModel}}List.map {{> to_string}}{{/isModel}}{{/items}}{{/isContainer}}{{^isEnum}}{{#isString}}{{/isString}}{{#isLong}}Int64.to_string {{/isLong}}{{#isInteger}}Int32.to_string {{/isInteger}}{{#isFloat}}string_of_float {{/isFloat}}{{#isNumber}}string_of_float {{/isNumber}}{{#isDouble}}string_of_float {{/isDouble}}{{#isBoolean}}string_of_bool {{/isBoolean}}{{#isByteArray}}Bytes.to_string {{/isByteArray}}{{#isModel}}{{{vendorExtensions.x-modelModule}}}.show {{/isModel}}{{/isEnum}}{{^isModel}}{{^isContainer}}{{#isEnum}}Enums.show_{{{datatypeWithEnum}}} {{/isEnum}}{{/isContainer}}{{/isModel}} \ No newline at end of file diff --git a/samples/client/petstore/ocaml-client/.openapi-generator-ignore b/samples/client/petstore/ocaml-client/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/samples/client/petstore/ocaml-client/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/petstore/ocaml-client/.openapi-generator/VERSION b/samples/client/petstore/ocaml-client/.openapi-generator/VERSION new file mode 100644 index 00000000000..717311e32e3 --- /dev/null +++ b/samples/client/petstore/ocaml-client/.openapi-generator/VERSION @@ -0,0 +1 @@ +unset \ No newline at end of file diff --git a/samples/client/petstore/ocaml-client/bin/dune b/samples/client/petstore/ocaml-client/bin/dune new file mode 100644 index 00000000000..03e93b0036b --- /dev/null +++ b/samples/client/petstore/ocaml-client/bin/dune @@ -0,0 +1,6 @@ +(include_subdirs no) +(executable + (name test) + (libraries petstore_client) + (modules test) +) diff --git a/samples/client/petstore/ocaml-client/bin/test.ml b/samples/client/petstore/ocaml-client/bin/test.ml new file mode 100644 index 00000000000..0fe314c1e72 --- /dev/null +++ b/samples/client/petstore/ocaml-client/bin/test.ml @@ -0,0 +1,19 @@ +open Petstore_client +open Lwt + +let lift f r = Ppx_deriving_yojson_runtime.(>|=) r f + +let main () = + let p = Pet.create "Bob" [] in + Pet_api.add_pet p + +let find_pet () = + let pet_id = 9199424981609334637L in + Pet_api.get_pet_by_id pet_id >|= Pet.show >|= print_endline + +let find_pets_by_tags () = + let tags = ["dog"; "cat"] in + Pet_api.find_pets_by_tags tags >|= List.map Pet.show >|= List.map print_endline + +let _ = + Lwt_main.run (find_pets_by_tags ()) diff --git a/samples/client/petstore/ocaml-client/dune b/samples/client/petstore/ocaml-client/dune new file mode 100644 index 00000000000..ed1c4d90e3d --- /dev/null +++ b/samples/client/petstore/ocaml-client/dune @@ -0,0 +1,9 @@ +(include_subdirs unqualified) +(library + (name petstore_client) + (public_name petstore_client) + (flags (:standard -w -27)) + (libraries str cohttp-lwt-unix lwt yojson ppx_deriving_yojson.runtime) + (preprocess (pps ppx_deriving_yojson ppx_deriving.std)) + (wrapped true) +) \ No newline at end of file diff --git a/samples/client/petstore/ocaml-client/dune-project b/samples/client/petstore/ocaml-client/dune-project new file mode 100644 index 00000000000..79d86e3c901 --- /dev/null +++ b/samples/client/petstore/ocaml-client/dune-project @@ -0,0 +1,2 @@ +(lang dune 1.10) +(name petstore_client) \ No newline at end of file diff --git a/samples/client/petstore/ocaml-client/petstore_client.opam b/samples/client/petstore/ocaml-client/petstore_client.opam new file mode 100644 index 00000000000..3c3603c2f14 --- /dev/null +++ b/samples/client/petstore/ocaml-client/petstore_client.opam @@ -0,0 +1,15 @@ +opam-version: "2.0" +name: "petstore_client" +version: "1.0.0" +synopsis: "" +description: """ +Longer description +""" +maintainer: "Name " +authors: "Name " +license: "" +homepage: "" +bug-reports: "" +dev-repo: "" +depends: [ "ocaml" "ocamlfind" ] +build: ["dune" "build" "-p" name] \ No newline at end of file diff --git a/samples/client/petstore/ocaml-client/src/apis/pet_api.ml b/samples/client/petstore/ocaml-client/src/apis/pet_api.ml new file mode 100644 index 00000000000..207503b9061 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/apis/pet_api.ml @@ -0,0 +1,80 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let add_pet body = + let open Lwt in + let uri = Request.build_uri "/pet" in + let headers = Request.default_headers in + let body = Request.write_json_body Pet.to_yojson body in + Cohttp_lwt_unix.Client.call `POST uri ~headers ~body >>= fun (resp, body) -> + Request.handle_unit_response resp + +let delete_pet pet_id api_key = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}" in + let headers = Request.default_headers in + let headers = Cohttp.Header.add headers "api_key" (api_key) in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + Cohttp_lwt_unix.Client.call `DELETE uri ~headers >>= fun (resp, body) -> + Request.handle_unit_response resp + +let find_pets_by_status status = + let open Lwt in + let uri = Request.build_uri "/pet/findByStatus" in + let headers = Request.default_headers in + let uri = Uri.add_query_param uri ("status", List.map Enums.show_pet_status status) in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.read_json_body_as_list_of (JsonSupport.unwrap Pet.of_yojson) resp body + +let find_pets_by_tags tags = + let open Lwt in + let uri = Request.build_uri "/pet/findByTags" in + let headers = Request.default_headers in + let uri = Uri.add_query_param uri ("tags", tags) in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.read_json_body_as_list_of (JsonSupport.unwrap Pet.of_yojson) resp body + +let get_pet_by_id pet_id = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Pet.of_yojson) resp body + +let update_pet body = + let open Lwt in + let uri = Request.build_uri "/pet" in + let headers = Request.default_headers in + let body = Request.write_json_body Pet.to_yojson body in + Cohttp_lwt_unix.Client.call `PUT uri ~headers ~body >>= fun (resp, body) -> + Request.handle_unit_response resp + +let update_pet_with_form pet_id name status = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_param body ("name", name) in + let body = Request.add_form_encoded_body_param body ("status", status) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.call `POST uri ~headers ~body >>= fun (resp, body) -> + Request.handle_unit_response resp + +let upload_file pet_id additional_metadata file = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}/uploadImage" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_param body ("additional_metadata", additional_metadata) in + let body = Request.add_form_encoded_body_param body ("file", file) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.call `POST uri ~headers ~body >>= fun (resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Api_response.of_yojson) resp body + diff --git a/samples/client/petstore/ocaml-client/src/apis/pet_api.mli b/samples/client/petstore/ocaml-client/src/apis/pet_api.mli new file mode 100644 index 00000000000..0cc31e085cf --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/apis/pet_api.mli @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val add_pet : Pet.t -> unit Lwt.t +val delete_pet : int64 -> string -> unit Lwt.t +val find_pets_by_status : Enums.pet_status list -> Pet.t list Lwt.t +val find_pets_by_tags : string list -> Pet.t list Lwt.t +val get_pet_by_id : int64 -> Pet.t Lwt.t +val update_pet : Pet.t -> unit Lwt.t +val update_pet_with_form : int64 -> string -> string -> unit Lwt.t +val upload_file : int64 -> string -> string -> Api_response.t Lwt.t diff --git a/samples/client/petstore/ocaml-client/src/apis/store_api.ml b/samples/client/petstore/ocaml-client/src/apis/store_api.ml new file mode 100644 index 00000000000..cebccabdd85 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/apis/store_api.ml @@ -0,0 +1,38 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let delete_order order_id = + let open Lwt in + let uri = Request.build_uri "/store/order/{orderId}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "orderId" (order_id) in + Cohttp_lwt_unix.Client.call `DELETE uri ~headers >>= fun (resp, body) -> + Request.handle_unit_response resp + +let get_inventory () = + let open Lwt in + let uri = Request.build_uri "/store/inventory" in + let headers = Request.default_headers in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.read_json_body_as_map_of (JsonSupport.to_int32) resp body + +let get_order_by_id order_id = + let open Lwt in + let uri = Request.build_uri "/store/order/{orderId}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "orderId" (Int64.to_string order_id) in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Order.of_yojson) resp body + +let place_order body = + let open Lwt in + let uri = Request.build_uri "/store/order" in + let headers = Request.default_headers in + let body = Request.write_json_body Order.to_yojson body in + Cohttp_lwt_unix.Client.call `POST uri ~headers ~body >>= fun (resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Order.of_yojson) resp body + diff --git a/samples/client/petstore/ocaml-client/src/apis/store_api.mli b/samples/client/petstore/ocaml-client/src/apis/store_api.mli new file mode 100644 index 00000000000..bc3c93eb494 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/apis/store_api.mli @@ -0,0 +1,11 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val delete_order : string -> unit Lwt.t +val get_inventory : unit -> (string * int32) list Lwt.t +val get_order_by_id : int64 -> Order.t Lwt.t +val place_order : Order.t -> Order.t Lwt.t diff --git a/samples/client/petstore/ocaml-client/src/apis/user_api.ml b/samples/client/petstore/ocaml-client/src/apis/user_api.ml new file mode 100644 index 00000000000..d05d71682a3 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/apis/user_api.ml @@ -0,0 +1,72 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let create_user body = + let open Lwt in + let uri = Request.build_uri "/user" in + let headers = Request.default_headers in + let body = Request.write_json_body User.to_yojson body in + Cohttp_lwt_unix.Client.call `POST uri ~headers ~body >>= fun (resp, body) -> + Request.handle_unit_response resp + +let create_users_with_array_input body = + let open Lwt in + let uri = Request.build_uri "/user/createWithArray" in + let headers = Request.default_headers in + let body = Request.write_json_body (JsonSupport.of_list_of User.to_yojson) body in + Cohttp_lwt_unix.Client.call `POST uri ~headers ~body >>= fun (resp, body) -> + Request.handle_unit_response resp + +let create_users_with_list_input body = + let open Lwt in + let uri = Request.build_uri "/user/createWithList" in + let headers = Request.default_headers in + let body = Request.write_json_body (JsonSupport.of_list_of User.to_yojson) body in + Cohttp_lwt_unix.Client.call `POST uri ~headers ~body >>= fun (resp, body) -> + Request.handle_unit_response resp + +let delete_user username = + let open Lwt in + let uri = Request.build_uri "/user/{username}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "username" (username) in + Cohttp_lwt_unix.Client.call `DELETE uri ~headers >>= fun (resp, body) -> + Request.handle_unit_response resp + +let get_user_by_name username = + let open Lwt in + let uri = Request.build_uri "/user/{username}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "username" (username) in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap User.of_yojson) resp body + +let login_user username password = + let open Lwt in + let uri = Request.build_uri "/user/login" in + let headers = Request.default_headers in + let uri = Uri.add_query_param' uri ("username", username) in + let uri = Uri.add_query_param' uri ("password", password) in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.read_json_body_as (JsonSupport.to_string) resp body + +let logout_user () = + let open Lwt in + let uri = Request.build_uri "/user/logout" in + let headers = Request.default_headers in + Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) -> + Request.handle_unit_response resp + +let update_user username body = + let open Lwt in + let uri = Request.build_uri "/user/{username}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "username" (username) in + let body = Request.write_json_body User.to_yojson body in + Cohttp_lwt_unix.Client.call `PUT uri ~headers ~body >>= fun (resp, body) -> + Request.handle_unit_response resp + diff --git a/samples/client/petstore/ocaml-client/src/apis/user_api.mli b/samples/client/petstore/ocaml-client/src/apis/user_api.mli new file mode 100644 index 00000000000..5191a2ea41b --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/apis/user_api.mli @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val create_user : User.t -> unit Lwt.t +val create_users_with_array_input : User.t list -> unit Lwt.t +val create_users_with_list_input : User.t list -> unit Lwt.t +val delete_user : string -> unit Lwt.t +val get_user_by_name : string -> User.t Lwt.t +val login_user : string -> string -> string Lwt.t +val logout_user : unit -> unit Lwt.t +val update_user : string -> User.t -> unit Lwt.t diff --git a/samples/client/petstore/ocaml-client/src/models/api_response.ml b/samples/client/petstore/ocaml-client/src/models/api_response.ml new file mode 100644 index 00000000000..f1b960d1449 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/models/api_response.ml @@ -0,0 +1,21 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Api_response.t : Describes the result of uploading an image resource + *) + +type t = { + code: int32 option [@default None]; + _type: string option [@default None]; + message: string option [@default None]; +} [@@deriving yojson, show ];; + +(** Describes the result of uploading an image resource *) +let create () : t = { + code = None; + _type = None; + message = None; +} + diff --git a/samples/client/petstore/ocaml-client/src/models/category.ml b/samples/client/petstore/ocaml-client/src/models/category.ml new file mode 100644 index 00000000000..31b9c3aab1d --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/models/category.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Category.t : A category for a pet + *) + +type t = { + id: int64 option [@default None]; + name: string option [@default None]; +} [@@deriving yojson, show ];; + +(** A category for a pet *) +let create () : t = { + id = None; + name = None; +} + diff --git a/samples/client/petstore/ocaml-client/src/models/order.ml b/samples/client/petstore/ocaml-client/src/models/order.ml new file mode 100644 index 00000000000..6130f88fd95 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/models/order.ml @@ -0,0 +1,28 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Order.t : An order for a pets from the pet store + *) + +type t = { + id: int64 option [@default None]; + pet_id: int64 option [@default None]; + quantity: int32 option [@default None]; + ship_date: string option [@default None]; + (* Order Status *) + status: Enums.status option [@default None]; + complete: bool option [@default None]; +} [@@deriving yojson, show ];; + +(** An order for a pets from the pet store *) +let create () : t = { + id = None; + pet_id = None; + quantity = None; + ship_date = None; + status = None; + complete = None; +} + diff --git a/samples/client/petstore/ocaml-client/src/models/pet.ml b/samples/client/petstore/ocaml-client/src/models/pet.ml new file mode 100644 index 00000000000..5d267ef32db --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/models/pet.ml @@ -0,0 +1,28 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Pet.t : A pet for sale in the pet store + *) + +type t = { + id: int64 option [@default None]; + category: Category.t option [@default None]; + name: string; + photo_urls: string list; + tags: Tag.t list; + (* pet status in the store *) + status: Enums.pet_status option [@default None]; +} [@@deriving yojson, show ];; + +(** A pet for sale in the pet store *) +let create (name : string) (photo_urls : string list) : t = { + id = None; + category = None; + name = name; + photo_urls = photo_urls; + tags = []; + status = None; +} + diff --git a/samples/client/petstore/ocaml-client/src/models/tag.ml b/samples/client/petstore/ocaml-client/src/models/tag.ml new file mode 100644 index 00000000000..5570d9c8eaf --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/models/tag.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Tag.t : A tag for a pet + *) + +type t = { + id: int64 option [@default None]; + name: string option [@default None]; +} [@@deriving yojson, show ];; + +(** A tag for a pet *) +let create () : t = { + id = None; + name = None; +} + diff --git a/samples/client/petstore/ocaml-client/src/models/user.ml b/samples/client/petstore/ocaml-client/src/models/user.ml new file mode 100644 index 00000000000..a9483d72889 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/models/user.ml @@ -0,0 +1,32 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema User.t : A User who is purchasing from the pet store + *) + +type t = { + id: int64 option [@default None]; + username: string option [@default None]; + first_name: string option [@default None]; + last_name: string option [@default None]; + email: string option [@default None]; + password: string option [@default None]; + phone: string option [@default None]; + (* User Status *) + user_status: int32 option [@default None]; +} [@@deriving yojson, show ];; + +(** A User who is purchasing from the pet store *) +let create () : t = { + id = None; + username = None; + first_name = None; + last_name = None; + email = None; + password = None; + phone = None; + user_status = None; +} + diff --git a/samples/client/petstore/ocaml-client/src/support/enums.ml b/samples/client/petstore/ocaml-client/src/support/enums.ml new file mode 100644 index 00000000000..0c64f8c042f --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/support/enums.ml @@ -0,0 +1,30 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type status = [ +| `Placed [@printer fun fmt _ -> Format.pp_print_string fmt "placed"] [@name "placed"] +| `Approved [@printer fun fmt _ -> Format.pp_print_string fmt "approved"] [@name "approved"] +| `Delivered [@printer fun fmt _ -> Format.pp_print_string fmt "delivered"] [@name "delivered"] +] [@@deriving yojson, show { with_path = false }];; + +let status_of_yojson json = status_of_yojson (`List [json]) +let status_to_yojson e = + match status_to_yojson e with + | `List [json] -> json + | json -> json + +type pet_status = [ +| `Available [@printer fun fmt _ -> Format.pp_print_string fmt "available"] [@name "available"] +| `Pending [@printer fun fmt _ -> Format.pp_print_string fmt "pending"] [@name "pending"] +| `Sold [@printer fun fmt _ -> Format.pp_print_string fmt "sold"] [@name "sold"] +] [@@deriving yojson, show { with_path = false }];; + +let pet_status_of_yojson json = pet_status_of_yojson (`List [json]) +let pet_status_to_yojson e = + match pet_status_to_yojson e with + | `List [json] -> json + | json -> json diff --git a/samples/client/petstore/ocaml-client/src/support/jsonSupport.ml b/samples/client/petstore/ocaml-client/src/support/jsonSupport.ml new file mode 100644 index 00000000000..4b0fac77545 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/support/jsonSupport.ml @@ -0,0 +1,55 @@ +open Ppx_deriving_yojson_runtime + +let unwrap to_json json = + match to_json json with + | Result.Ok json -> json + | Result.Error s -> failwith s + +let to_int json = + match json with + | `Int x -> x + | `Intlit s -> int_of_string s + | _ -> failwith "JsonSupport.to_int" + +let to_bool json = + match json with + | `Bool x -> x + | _ -> failwith "JsonSupport.to_bool" + +let to_float json = + match json with + | `Float x -> x + | _ -> failwith "JsonSupport.to_float" + +let to_string json = + match json with + | `String s -> s + | _ -> failwith "JsonSupport.to_string" + +let to_int32 json : int32 = + match json with + | `Int x -> Int32.of_int x + | `Intlit s -> Int32.of_string s + | _ -> failwith "JsonSupport.to_int32" + +let to_int64 json : int64 = + match json with + | `Int x -> Int64.of_int x + | `Intlit s -> Int64.of_string s + | _ -> failwith "JsonSupport.to_int64" + +let of_int x = `Int x + +let of_bool b = `Bool b + +let of_float x = `Float x + +let of_string s = `String s + +let of_int32 x = `Intlit (Int32.to_string x) + +let of_int64 x = `Intlit (Int64.to_string x) + +let of_list_of of_f l = `List (List.map of_f l) + +let of_map_of of_f l = `Assoc (List.map (fun (k, v) -> (k, of_f v)) l) \ No newline at end of file diff --git a/samples/client/petstore/ocaml-client/src/support/request.ml b/samples/client/petstore/ocaml-client/src/support/request.ml new file mode 100644 index 00000000000..21b6f870ed9 --- /dev/null +++ b/samples/client/petstore/ocaml-client/src/support/request.ml @@ -0,0 +1,48 @@ +let api_key = "" +let base_url = "http://petstore.swagger.io/v2" +let default_headers = Cohttp.Header.init_with "Content-Type" "application/json" + +let build_uri operation_path = Uri.of_string (base_url ^ operation_path) +let write_json_body to_json payload = + to_json payload |> Yojson.Safe.to_string ~std:true |> Cohttp_lwt.Body.of_string + +let handle_response resp on_success_handler = + match Cohttp_lwt.Response.status resp with + | #Cohttp.Code.success_status -> on_success_handler () + | s -> failwith ("Server responded with status " ^ Cohttp.Code.(reason_phrase_of_code (code_of_status s))) + +let handle_unit_response resp = handle_response resp (fun () -> Lwt.return ()) + +let read_json_body resp body = + handle_response resp (fun () -> + (Lwt.(Cohttp_lwt.Body.to_string body >|= Yojson.Safe.from_string))) + +let read_json_body_as of_json resp body = + Lwt.(read_json_body resp body >|= of_json) + +let read_json_body_as_list resp body = + Lwt.(read_json_body resp body >|= Yojson.Safe.Util.to_list) + +let read_json_body_as_list_of of_json resp body = + Lwt.(read_json_body_as_list resp body >|= List.map of_json) + +let read_json_body_as_map_of of_json resp body = + Lwt.(read_json_body resp body >|= Yojson.Safe.Util.to_assoc >|= List.map (fun (s, v) -> (s, of_json v))) + +let replace_path_param uri param_name param_value = + let regexp = Str.regexp (Str.quote ("{" ^ param_name ^ "}")) in + let path = Str.global_replace regexp param_value (Uri.path uri) in + Uri.with_path uri path + +let init_form_encoded_body () = "" + +let add_form_encoded_body_param params (paramName, paramValue) = + let new_param_enc = Printf.sprintf {|%s=%s|} (Uri.pct_encode paramName) (Uri.pct_encode paramValue) in + if params = "" + then new_param_enc + else Printf.sprintf {|%s&%s|} params new_param_enc + +let add_form_encoded_body_params params (paramName, new_params) = + add_form_encoded_body_param params (paramName, String.concat "," new_params) + +let finalize_form_encoded_body body = Cohttp_lwt.Body.of_string body diff --git a/samples/openapi3/client/petstore/ocaml-client/.openapi-generator-ignore b/samples/openapi3/client/petstore/ocaml-client/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/openapi3/client/petstore/ocaml-client/.openapi-generator/VERSION b/samples/openapi3/client/petstore/ocaml-client/.openapi-generator/VERSION new file mode 100644 index 00000000000..717311e32e3 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/.openapi-generator/VERSION @@ -0,0 +1 @@ +unset \ No newline at end of file diff --git a/samples/openapi3/client/petstore/ocaml-client/dune b/samples/openapi3/client/petstore/ocaml-client/dune new file mode 100644 index 00000000000..ed1c4d90e3d --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/dune @@ -0,0 +1,9 @@ +(include_subdirs unqualified) +(library + (name petstore_client) + (public_name petstore_client) + (flags (:standard -w -27)) + (libraries str cohttp-lwt-unix lwt yojson ppx_deriving_yojson.runtime) + (preprocess (pps ppx_deriving_yojson ppx_deriving.std)) + (wrapped true) +) \ No newline at end of file diff --git a/samples/openapi3/client/petstore/ocaml-client/dune-project b/samples/openapi3/client/petstore/ocaml-client/dune-project new file mode 100644 index 00000000000..79d86e3c901 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/dune-project @@ -0,0 +1,2 @@ +(lang dune 1.10) +(name petstore_client) \ No newline at end of file diff --git a/samples/openapi3/client/petstore/ocaml-client/petstore_client.opam b/samples/openapi3/client/petstore/ocaml-client/petstore_client.opam new file mode 100644 index 00000000000..3c3603c2f14 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/petstore_client.opam @@ -0,0 +1,15 @@ +opam-version: "2.0" +name: "petstore_client" +version: "1.0.0" +synopsis: "" +description: """ +Longer description +""" +maintainer: "Name " +authors: "Name " +license: "" +homepage: "" +bug-reports: "" +dev-repo: "" +depends: [ "ocaml" "ocamlfind" ] +build: ["dune" "build" "-p" name] \ No newline at end of file diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/another_fake_api.ml b/samples/openapi3/client/petstore/ocaml-client/src/apis/another_fake_api.ml new file mode 100644 index 00000000000..042919109b4 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/another_fake_api.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let call_123_test_special_tags client_t = + let open Lwt in + let uri = Request.build_uri "/another-fake/dummy" in + let headers = Request.default_headers in + let body = Request.write_json_body Client.to_yojson client_t in + Cohttp_lwt_unix.Client.patch uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Client.of_yojson) body + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/another_fake_api.mli b/samples/openapi3/client/petstore/ocaml-client/src/apis/another_fake_api.mli new file mode 100644 index 00000000000..2b93c08e959 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/another_fake_api.mli @@ -0,0 +1,8 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val call_123_test_special_tags : Client.t -> Client.t Lwt.t diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/default_api.ml b/samples/openapi3/client/petstore/ocaml-client/src/apis/default_api.ml new file mode 100644 index 00000000000..c432362bb02 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/default_api.ml @@ -0,0 +1,14 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let foo_get () = + let open Lwt in + let uri = Request.build_uri "/foo" in + let headers = Request.default_headers in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Inline_response_default.of_yojson) body + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/default_api.mli b/samples/openapi3/client/petstore/ocaml-client/src/apis/default_api.mli new file mode 100644 index 00000000000..f1392d7621c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/default_api.mli @@ -0,0 +1,8 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val foo_get : unit -> Inline_response_default.t Lwt.t diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_api.ml b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_api.ml new file mode 100644 index 00000000000..5f755065062 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_api.ml @@ -0,0 +1,136 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let fake_health_get () = + let open Lwt in + let uri = Request.build_uri "/fake/health" in + let headers = Request.default_headers in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Health_check_result.of_yojson) body + +let fake_outer_boolean_serialize body = + let open Lwt in + let uri = Request.build_uri "/fake/outer/boolean" in + let headers = Request.default_headers in + let body = Request.write_json_body JsonSupport.of_bool body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.to_bool) body + +let fake_outer_composite_serialize outer_composite_t = + let open Lwt in + let uri = Request.build_uri "/fake/outer/composite" in + let headers = Request.default_headers in + let body = Request.write_json_body Outer_composite.to_yojson outer_composite_t in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Outer_composite.of_yojson) body + +let fake_outer_number_serialize body = + let open Lwt in + let uri = Request.build_uri "/fake/outer/number" in + let headers = Request.default_headers in + let body = Request.write_json_body JsonSupport.of_float body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.to_float) body + +let fake_outer_string_serialize body = + let open Lwt in + let uri = Request.build_uri "/fake/outer/string" in + let headers = Request.default_headers in + let body = Request.write_json_body JsonSupport.of_string body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.to_string) body + +let test_body_with_file_schema file_schema_test_class_t = + let open Lwt in + let uri = Request.build_uri "/fake/body-with-file-schema" in + let headers = Request.default_headers in + let body = Request.write_json_body File_schema_test_class.to_yojson file_schema_test_class_t in + Cohttp_lwt_unix.Client.put uri ~headers ~body >>= fun (_resp, body) -> return () + +let test_body_with_query_params query user_t = + let open Lwt in + let uri = Request.build_uri "/fake/body-with-query-params" in + let headers = Request.default_headers in + let uri = Uri.add_query_param' uri ("query", query) in + let body = Request.write_json_body User.to_yojson user_t in + Cohttp_lwt_unix.Client.put uri ~headers ~body >>= fun (_resp, body) -> return () + +let test_client_model client_t = + let open Lwt in + let uri = Request.build_uri "/fake" in + let headers = Request.default_headers in + let body = Request.write_json_body Client.to_yojson client_t in + Cohttp_lwt_unix.Client.patch uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Client.of_yojson) body + +let test_endpoint_parameters number double pattern_without_delimiter byte integer int32 int64 float string binary date date_time password callback = + let open Lwt in + let uri = Request.build_uri "/fake" in + let headers = Request.default_headers in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_param body ("integer", Int32.to_string integer) in + let body = Request.add_form_encoded_body_param body ("int32", Int32.to_string int32) in + let body = Request.add_form_encoded_body_param body ("int64", Int64.to_string int64) in + let body = Request.add_form_encoded_body_param body ("number", string_of_float number) in + let body = Request.add_form_encoded_body_param body ("float", string_of_float float) in + let body = Request.add_form_encoded_body_param body ("double", string_of_float double) in + let body = Request.add_form_encoded_body_param body ("string", string) in + let body = Request.add_form_encoded_body_param body ("pattern_without_delimiter", pattern_without_delimiter) in + let body = Request.add_form_encoded_body_param body ("byte", Bytes.to_string byte) in + let body = Request.add_form_encoded_body_param body ("binary", binary) in + let body = Request.add_form_encoded_body_param body ("date", date) in + let body = Request.add_form_encoded_body_param body ("date_time", date_time) in + let body = Request.add_form_encoded_body_param body ("password", password) in + let body = Request.add_form_encoded_body_param body ("callback", callback) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> return () + +let test_enum_parameters enum_header_string_array enum_header_string enum_query_string_array enum_query_string enum_query_integer enum_query_double enum_form_string_array enum_form_string = + let open Lwt in + let uri = Request.build_uri "/fake" in + let headers = Request.default_headers in + let headers = Cohttp.Header.add_multi headers "enum_header_string_array" (List.map Enums.show_inline_object_2_enum_form_string_array enum_header_string_array) in + let headers = Cohttp.Header.add headers "enum_header_string" (Enums.show_enumclass enum_header_string) in + let uri = Uri.add_query_param uri ("enum_query_string_array", List.map Enums.show_inline_object_2_enum_form_string_array enum_query_string_array) in + let uri = Uri.add_query_param' uri ("enum_query_string", Enums.show_enumclass enum_query_string) in + let uri = Uri.add_query_param' uri ("enum_query_integer", Enums.show_enum_query_integer enum_query_integer) in + let uri = Uri.add_query_param' uri ("enum_query_double", Enums.show_enum_number enum_query_double) in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_params body ("enum_form_string_array", List.map Enums.show_inline_object_2_enum_form_string_array enum_form_string_array) in + let body = Request.add_form_encoded_body_param body ("enum_form_string", Enums.show_enumclass enum_form_string) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.get uri ~headers ~body >>= fun (_resp, body) -> return () + +let test_group_parameters required_string_group required_boolean_group required_int64_group string_group boolean_group int64_group = + let open Lwt in + let uri = Request.build_uri "/fake" in + let headers = Request.default_headers in + let headers = Cohttp.Header.add headers "required_boolean_group" (string_of_bool required_boolean_group) in + let headers = Cohttp.Header.add headers "boolean_group" (string_of_bool boolean_group) in + let uri = Uri.add_query_param' uri ("required_string_group", Int32.to_string required_string_group) in + let uri = Uri.add_query_param' uri ("required_int64_group", Int64.to_string required_int64_group) in + let uri = Uri.add_query_param' uri ("string_group", Int32.to_string string_group) in + let uri = Uri.add_query_param' uri ("int64_group", Int64.to_string int64_group) in + Cohttp_lwt_unix.Client.delete uri ~headers >>= fun (_resp, body) -> return () + +let test_inline_additional_properties request_body = + let open Lwt in + let uri = Request.build_uri "/fake/inline-additionalProperties" in + let headers = Request.default_headers in + let body = Request.write_json_body (JsonSupport.of_map_of JsonSupport.of_string) request_body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> return () + +let test_json_form_data param param2 = + let open Lwt in + let uri = Request.build_uri "/fake/jsonFormData" in + let headers = Request.default_headers in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_param body ("param", param) in + let body = Request.add_form_encoded_body_param body ("param2", param2) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.get uri ~headers ~body >>= fun (_resp, body) -> return () + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_api.mli b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_api.mli new file mode 100644 index 00000000000..bc6c25e2c40 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_api.mli @@ -0,0 +1,20 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val fake_health_get : unit -> Health_check_result.t Lwt.t +val fake_outer_boolean_serialize : bool -> bool Lwt.t +val fake_outer_composite_serialize : Outer_composite.t -> Outer_composite.t Lwt.t +val fake_outer_number_serialize : float -> float Lwt.t +val fake_outer_string_serialize : string -> string Lwt.t +val test_body_with_file_schema : File_schema_test_class.t -> unit Lwt.t +val test_body_with_query_params : string -> User.t -> unit Lwt.t +val test_client_model : Client.t -> Client.t Lwt.t +val test_endpoint_parameters : float -> float -> string -> bytes -> int32 -> int32 -> int64 -> float -> string -> string -> string -> string -> string -> string -> unit Lwt.t +val test_enum_parameters : Enums.inline_object_2_enum_form_string_array list -> Enums.enumclass -> Enums.inline_object_2_enum_form_string_array list -> Enums.enumclass -> Enums.enum_query_integer -> Enums.enum_number -> Enums.inline_object_2_enum_form_string_array list -> Enums.enumclass -> unit Lwt.t +val test_group_parameters : int32 -> bool -> int64 -> int32 -> bool -> int64 -> unit Lwt.t +val test_inline_additional_properties : (string * string) list -> unit Lwt.t +val test_json_form_data : string -> string -> unit Lwt.t diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_classname_tags123_api.ml b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_classname_tags123_api.ml new file mode 100644 index 00000000000..f108f7e0b20 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_classname_tags123_api.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let test_classname client_t = + let open Lwt in + let uri = Request.build_uri "/fake_classname_test" in + let headers = Request.default_headers in + let body = Request.write_json_body Client.to_yojson client_t in + Cohttp_lwt_unix.Client.patch uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Client.of_yojson) body + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_classname_tags123_api.mli b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_classname_tags123_api.mli new file mode 100644 index 00000000000..85059985bbe --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/fake_classname_tags123_api.mli @@ -0,0 +1,8 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val test_classname : Client.t -> Client.t Lwt.t diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/pet_api.ml b/samples/openapi3/client/petstore/ocaml-client/src/apis/pet_api.ml new file mode 100644 index 00000000000..9ba3f1ea0a8 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/pet_api.ml @@ -0,0 +1,88 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let add_pet pet_t = + let open Lwt in + let uri = Request.build_uri "/pet" in + let headers = Request.default_headers in + let body = Request.write_json_body Pet.to_yojson pet_t in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> return () + +let delete_pet pet_id api_key = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}" in + let headers = Request.default_headers in + let headers = Cohttp.Header.add headers "api_key" (api_key) in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + Cohttp_lwt_unix.Client.delete uri ~headers >>= fun (_resp, body) -> return () + +let find_pets_by_status status = + let open Lwt in + let uri = Request.build_uri "/pet/findByStatus" in + let headers = Request.default_headers in + let uri = Uri.add_query_param uri ("status", List.map Enums.show_pet_status status) in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as_list_of (JsonSupport.unwrap Pet.of_yojson) body + +let find_pets_by_tags tags = + let open Lwt in + let uri = Request.build_uri "/pet/findByTags" in + let headers = Request.default_headers in + let uri = Uri.add_query_param uri ("tags", tags) in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as_list_of (JsonSupport.unwrap Pet.of_yojson) body + +let get_pet_by_id pet_id = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Pet.of_yojson) body + +let update_pet pet_t = + let open Lwt in + let uri = Request.build_uri "/pet" in + let headers = Request.default_headers in + let body = Request.write_json_body Pet.to_yojson pet_t in + Cohttp_lwt_unix.Client.put uri ~headers ~body >>= fun (_resp, body) -> return () + +let update_pet_with_form pet_id name status = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_param body ("name", name) in + let body = Request.add_form_encoded_body_param body ("status", status) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> return () + +let upload_file pet_id additional_metadata file = + let open Lwt in + let uri = Request.build_uri "/pet/{petId}/uploadImage" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_param body ("additional_metadata", additional_metadata) in + let body = Request.add_form_encoded_body_param body ("file", file) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Api_response.of_yojson) body + +let upload_file_with_required_file pet_id required_file additional_metadata = + let open Lwt in + let uri = Request.build_uri "/fake/{petId}/uploadImageWithRequiredFile" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "petId" (Int64.to_string pet_id) in + let body = Request.init_form_encoded_body () in + let body = Request.add_form_encoded_body_param body ("additional_metadata", additional_metadata) in + let body = Request.add_form_encoded_body_param body ("required_file", required_file) in + let body = Request.finalize_form_encoded_body body in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Api_response.of_yojson) body + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/pet_api.mli b/samples/openapi3/client/petstore/ocaml-client/src/apis/pet_api.mli new file mode 100644 index 00000000000..a1036b6c3c7 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/pet_api.mli @@ -0,0 +1,16 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val add_pet : Pet.t -> unit Lwt.t +val delete_pet : int64 -> string -> unit Lwt.t +val find_pets_by_status : Enums.pet_status list -> Pet.t list Lwt.t +val find_pets_by_tags : string list -> Pet.t list Lwt.t +val get_pet_by_id : int64 -> Pet.t Lwt.t +val update_pet : Pet.t -> unit Lwt.t +val update_pet_with_form : int64 -> string -> string -> unit Lwt.t +val upload_file : int64 -> string -> string -> Api_response.t Lwt.t +val upload_file_with_required_file : int64 -> string -> string -> Api_response.t Lwt.t diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/store_api.ml b/samples/openapi3/client/petstore/ocaml-client/src/apis/store_api.ml new file mode 100644 index 00000000000..79cc1ccc0ea --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/store_api.ml @@ -0,0 +1,37 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let delete_order order_id = + let open Lwt in + let uri = Request.build_uri "/store/order/{order_id}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "order_id" (order_id) in + Cohttp_lwt_unix.Client.delete uri ~headers >>= fun (_resp, body) -> return () + +let get_inventory () = + let open Lwt in + let uri = Request.build_uri "/store/inventory" in + let headers = Request.default_headers in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as_map_of (JsonSupport.to_int32) body + +let get_order_by_id order_id = + let open Lwt in + let uri = Request.build_uri "/store/order/{order_id}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "order_id" (Int64.to_string order_id) in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Order.of_yojson) body + +let place_order order_t = + let open Lwt in + let uri = Request.build_uri "/store/order" in + let headers = Request.default_headers in + let body = Request.write_json_body Order.to_yojson order_t in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap Order.of_yojson) body + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/store_api.mli b/samples/openapi3/client/petstore/ocaml-client/src/apis/store_api.mli new file mode 100644 index 00000000000..bc3c93eb494 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/store_api.mli @@ -0,0 +1,11 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val delete_order : string -> unit Lwt.t +val get_inventory : unit -> (string * int32) list Lwt.t +val get_order_by_id : int64 -> Order.t Lwt.t +val place_order : Order.t -> Order.t Lwt.t diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/user_api.ml b/samples/openapi3/client/petstore/ocaml-client/src/apis/user_api.ml new file mode 100644 index 00000000000..d9499ee070e --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/user_api.ml @@ -0,0 +1,66 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +let create_user user_t = + let open Lwt in + let uri = Request.build_uri "/user" in + let headers = Request.default_headers in + let body = Request.write_json_body User.to_yojson user_t in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> return () + +let create_users_with_array_input user = + let open Lwt in + let uri = Request.build_uri "/user/createWithArray" in + let headers = Request.default_headers in + let body = Request.write_json_body (JsonSupport.of_list_of User.to_yojson) user in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> return () + +let create_users_with_list_input user = + let open Lwt in + let uri = Request.build_uri "/user/createWithList" in + let headers = Request.default_headers in + let body = Request.write_json_body (JsonSupport.of_list_of User.to_yojson) user in + Cohttp_lwt_unix.Client.post uri ~headers ~body >>= fun (_resp, body) -> return () + +let delete_user username = + let open Lwt in + let uri = Request.build_uri "/user/{username}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "username" (username) in + Cohttp_lwt_unix.Client.delete uri ~headers >>= fun (_resp, body) -> return () + +let get_user_by_name username = + let open Lwt in + let uri = Request.build_uri "/user/{username}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "username" (username) in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.unwrap User.of_yojson) body + +let login_user username password = + let open Lwt in + let uri = Request.build_uri "/user/login" in + let headers = Request.default_headers in + let uri = Uri.add_query_param' uri ("username", username) in + let uri = Uri.add_query_param' uri ("password", password) in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> + Request.read_json_body_as (JsonSupport.to_string) body + +let logout_user () = + let open Lwt in + let uri = Request.build_uri "/user/logout" in + let headers = Request.default_headers in + Cohttp_lwt_unix.Client.get uri ~headers >>= fun (_resp, body) -> return () + +let update_user username user_t = + let open Lwt in + let uri = Request.build_uri "/user/{username}" in + let headers = Request.default_headers in + let uri = Request.replace_path_param uri "username" (username) in + let body = Request.write_json_body User.to_yojson user_t in + Cohttp_lwt_unix.Client.put uri ~headers ~body >>= fun (_resp, body) -> return () + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/apis/user_api.mli b/samples/openapi3/client/petstore/ocaml-client/src/apis/user_api.mli new file mode 100644 index 00000000000..5191a2ea41b --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/apis/user_api.mli @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +val create_user : User.t -> unit Lwt.t +val create_users_with_array_input : User.t list -> unit Lwt.t +val create_users_with_list_input : User.t list -> unit Lwt.t +val delete_user : string -> unit Lwt.t +val get_user_by_name : string -> User.t Lwt.t +val login_user : string -> string -> string Lwt.t +val logout_user : unit -> unit Lwt.t +val update_user : string -> User.t -> unit Lwt.t diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/additional_properties_class.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/additional_properties_class.ml new file mode 100644 index 00000000000..8e5f7b075f9 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/additional_properties_class.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + map_property: (string * string) list; + map_of_map_property: (string * (string * string) list) list; +} [@@deriving yojson, show ];; + +let create () : t = { + map_property = []; + map_of_map_property = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/animal.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/animal.ml new file mode 100644 index 00000000000..637ecdf60a9 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/animal.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + class_name: string; + color: string option; +} [@@deriving yojson, show ];; + +let create (class_name : string) : t = { + class_name = class_name; + color = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/api_response.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/api_response.ml new file mode 100644 index 00000000000..3f23662e01a --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/api_response.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + code: int32 option; + _type: string option; + message: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + code = None; + _type = None; + message = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/array_of_array_of_number_only.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/array_of_array_of_number_only.ml new file mode 100644 index 00000000000..2204bac4b6c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/array_of_array_of_number_only.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + array_array_number: float list list; +} [@@deriving yojson, show ];; + +let create () : t = { + array_array_number = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/array_of_number_only.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/array_of_number_only.ml new file mode 100644 index 00000000000..3708294193e --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/array_of_number_only.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + array_number: float list; +} [@@deriving yojson, show ];; + +let create () : t = { + array_number = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/array_test.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/array_test.ml new file mode 100644 index 00000000000..6198edd88a6 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/array_test.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + array_of_string: string list; + array_array_of_integer: int64 list list; + array_array_of_model: Read_only_first.t list list; +} [@@deriving yojson, show ];; + +let create () : t = { + array_of_string = []; + array_array_of_integer = []; + array_array_of_model = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/capitalization.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/capitalization.ml new file mode 100644 index 00000000000..c75a3e4574b --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/capitalization.ml @@ -0,0 +1,26 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + small_camel: string option; + capital_camel: string option; + small_snake: string option; + capital_snake: string option; + sca_eth_flow_points: string option; + (* Name of the pet *) + att_name: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + small_camel = None; + capital_camel = None; + small_snake = None; + capital_snake = None; + sca_eth_flow_points = None; + att_name = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/cat.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/cat.ml new file mode 100644 index 00000000000..1d79ca8716f --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/cat.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + class_name: string; + color: string option; + declawed: bool option; +} [@@deriving yojson, show ];; + +let create (class_name : string) : t = { + class_name = class_name; + color = None; + declawed = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/cat_all_of.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/cat_all_of.ml new file mode 100644 index 00000000000..d0c18e1a505 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/cat_all_of.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + declawed: bool option; +} [@@deriving yojson, show ];; + +let create () : t = { + declawed = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/category.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/category.ml new file mode 100644 index 00000000000..fdace8a8372 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/category.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + id: int64 option; + name: string; +} [@@deriving yojson, show ];; + +let create (name : string) : t = { + id = None; + name = name; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/class_model.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/class_model.ml new file mode 100644 index 00000000000..8023b7cdcbd --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/class_model.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Class_model.t : Model for testing model with \\"_class\\" property + *) + +type t = { + _class: string option; +} [@@deriving yojson, show ];; + +(** Model for testing model with \\"_class\\" property *) +let create () : t = { + _class = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/client.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/client.ml new file mode 100644 index 00000000000..259a2b3c139 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/client.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + client: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + client = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/dog.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/dog.ml new file mode 100644 index 00000000000..ceaa4b66b7d --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/dog.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + class_name: string; + color: string option; + breed: string option; +} [@@deriving yojson, show ];; + +let create (class_name : string) : t = { + class_name = class_name; + color = None; + breed = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/dog_all_of.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/dog_all_of.ml new file mode 100644 index 00000000000..7bbf7ec7275 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/dog_all_of.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + breed: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + breed = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/enum_arrays.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/enum_arrays.ml new file mode 100644 index 00000000000..5dc755407d1 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/enum_arrays.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + just_symbol: Enums.just_symbol option; + array_enum: Enums.enumarrays_array_enum list; +} [@@deriving yojson, show ];; + +let create () : t = { + just_symbol = None; + array_enum = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/enum_test.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/enum_test.ml new file mode 100644 index 00000000000..5a92f51ff70 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/enum_test.ml @@ -0,0 +1,29 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + enum_string: Enums.enum_string option; + enum_string_required: Enums.enum_string; + enum_integer: Enums.enum_integer option; + enum_number: Enums.enum_number option; + outer_enum: Enums.status option; + outer_enum_integer: Enums.outerenuminteger option; + outer_enum_default_value: Enums.status option; + outer_enum_integer_default_value: Enums.outerenuminteger option; +} [@@deriving yojson, show ];; + +let create (enum_string_required : Enums.enum_string) : t = { + enum_string = None; + enum_string_required = enum_string_required; + enum_integer = None; + enum_number = None; + outer_enum = None; + outer_enum_integer = None; + outer_enum_default_value = None; + outer_enum_integer_default_value = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/file.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/file.ml new file mode 100644 index 00000000000..fd79bb76abf --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/file.ml @@ -0,0 +1,18 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema File.t : Must be named `File` for test. + *) + +type t = { + (* Test capitalization *) + source_uri: string option; +} [@@deriving yojson, show ];; + +(** Must be named `File` for test. *) +let create () : t = { + source_uri = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/file_schema_test_class.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/file_schema_test_class.ml new file mode 100644 index 00000000000..b0938b230f2 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/file_schema_test_class.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + file: File.t option; + files: File.t list; +} [@@deriving yojson, show ];; + +let create () : t = { + file = None; + files = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/foo.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/foo.ml new file mode 100644 index 00000000000..e4d05a7971a --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/foo.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + bar: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + bar = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/format_test.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/format_test.ml new file mode 100644 index 00000000000..1a5b28c9af2 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/format_test.ml @@ -0,0 +1,45 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + integer: int32 option; + int32: int32 option; + int64: int64 option; + number: float; + float: float option; + double: float option; + string: string option; + byte: bytes; + binary: string option; + date: string; + date_time: string option; + uuid: string option; + password: string; + (* A string that is a 10 digit number. Can have leading zeros. *) + pattern_with_digits: string option; + (* A string starting with 'image_' (case insensitive) and one to three digits following i.e. Image_01. *) + pattern_with_digits_and_delimiter: string option; +} [@@deriving yojson, show ];; + +let create (number : float) (byte : bytes) (date : string) (password : string) : t = { + integer = None; + int32 = None; + int64 = None; + number = number; + float = None; + double = None; + string = None; + byte = byte; + binary = None; + date = date; + date_time = None; + uuid = None; + password = password; + pattern_with_digits = None; + pattern_with_digits_and_delimiter = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/has_only_read_only.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/has_only_read_only.ml new file mode 100644 index 00000000000..f1fb4c639c9 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/has_only_read_only.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + bar: string option; + foo: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + bar = None; + foo = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/health_check_result.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/health_check_result.ml new file mode 100644 index 00000000000..6103f54fa2c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/health_check_result.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Health_check_result.t : Just a string to inform instance is up and running. Make it nullable in hope to get it as pointer in generated model. + *) + +type t = { + nullable_message: string option; +} [@@deriving yojson, show ];; + +(** Just a string to inform instance is up and running. Make it nullable in hope to get it as pointer in generated model. *) +let create () : t = { + nullable_message = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object.ml new file mode 100644 index 00000000000..092a7bca691 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + (* Updated name of the pet *) + name: string option; + (* Updated status of the pet *) + status: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + name = None; + status = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_1.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_1.ml new file mode 100644 index 00000000000..be3c829f5e0 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_1.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + (* Additional data to pass to server *) + additional_metadata: string option; + (* file to upload *) + file: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + additional_metadata = None; + file = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_2.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_2.ml new file mode 100644 index 00000000000..433587a195c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_2.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + (* Form parameter enum test (string array) *) + enum_form_string_array: Enums.inline_object_2_enum_form_string_array list; + (* Form parameter enum test (string) *) + enum_form_string: Enums.enumclass option; +} [@@deriving yojson, show ];; + +let create () : t = { + enum_form_string_array = []; + enum_form_string = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_3.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_3.ml new file mode 100644 index 00000000000..9ae5a0c464d --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_3.ml @@ -0,0 +1,55 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + (* None *) + integer: int32 option; + (* None *) + int32: int32 option; + (* None *) + int64: int64 option; + (* None *) + number: float; + (* None *) + float: float option; + (* None *) + double: float; + (* None *) + string: string option; + (* None *) + pattern_without_delimiter: string; + (* None *) + byte: bytes; + (* None *) + binary: string option; + (* None *) + date: string option; + (* None *) + date_time: string option; + (* None *) + password: string option; + (* None *) + callback: string option; +} [@@deriving yojson, show ];; + +let create (number : float) (double : float) (pattern_without_delimiter : string) (byte : bytes) : t = { + integer = None; + int32 = None; + int64 = None; + number = number; + float = None; + double = double; + string = None; + pattern_without_delimiter = pattern_without_delimiter; + byte = byte; + binary = None; + date = None; + date_time = None; + password = None; + callback = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_4.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_4.ml new file mode 100644 index 00000000000..1291f3285ed --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_4.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + (* field1 *) + param: string; + (* field2 *) + param2: string; +} [@@deriving yojson, show ];; + +let create (param : string) (param2 : string) : t = { + param = param; + param2 = param2; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_5.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_5.ml new file mode 100644 index 00000000000..9e4f0b04b27 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_object_5.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + (* Additional data to pass to server *) + additional_metadata: string option; + (* file to upload *) + required_file: string; +} [@@deriving yojson, show ];; + +let create (required_file : string) : t = { + additional_metadata = None; + required_file = required_file; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/inline_response_default.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_response_default.ml new file mode 100644 index 00000000000..c5b36a2ffd4 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/inline_response_default.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + string: Foo.t option; +} [@@deriving yojson, show ];; + +let create () : t = { + string = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/map_test.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/map_test.ml new file mode 100644 index 00000000000..8b463f70791 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/map_test.ml @@ -0,0 +1,21 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + map_map_of_string: (string * (string * string) list) list; + map_of_enum_string: (string * Enums.maptest_map_of_enum_string) list; + direct_map: (string * bool) list; + indirect_map: (string * bool) list; +} [@@deriving yojson, show ];; + +let create () : t = { + map_map_of_string = []; + map_of_enum_string = []; + direct_map = []; + indirect_map = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/mixed_properties_and_additional_properties_class.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/mixed_properties_and_additional_properties_class.ml new file mode 100644 index 00000000000..3cae9de2711 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/mixed_properties_and_additional_properties_class.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + uuid: string option; + date_time: string option; + map: (string * Animal.t) list; +} [@@deriving yojson, show ];; + +let create () : t = { + uuid = None; + date_time = None; + map = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/model_200_response.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/model_200_response.ml new file mode 100644 index 00000000000..f8065e45dfc --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/model_200_response.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Model_200_response.t : Model for testing model name starting with number + *) + +type t = { + name: int32 option; + _class: string option; +} [@@deriving yojson, show ];; + +(** Model for testing model name starting with number *) +let create () : t = { + name = None; + _class = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/model__special_model_name_.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/model__special_model_name_.ml new file mode 100644 index 00000000000..5e70029989c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/model__special_model_name_.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + special_property_name: int64 option; +} [@@deriving yojson, show ];; + +let create () : t = { + special_property_name = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/name.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/name.ml new file mode 100644 index 00000000000..6a8377a933d --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/name.ml @@ -0,0 +1,23 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Name.t : Model for testing model name same as property name + *) + +type t = { + name: int32; + snake_case: int32 option; + property: string option; + var_123_number: int32 option; +} [@@deriving yojson, show ];; + +(** Model for testing model name same as property name *) +let create (name : int32) : t = { + name = name; + snake_case = None; + property = None; + var_123_number = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/nullable_class.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/nullable_class.ml new file mode 100644 index 00000000000..1787dd6dd00 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/nullable_class.ml @@ -0,0 +1,37 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + integer_prop: int32 option; + number_prop: float option; + boolean_prop: bool option; + string_prop: string option; + date_prop: string option; + datetime_prop: string option; + array_nullable_prop: Yojson.Safe.t list; + array_and_items_nullable_prop: Yojson.Safe.t list; + array_items_nullable: Yojson.Safe.t list; + object_nullable_prop: (string * Yojson.Safe.t) list; + object_and_items_nullable_prop: (string * Yojson.Safe.t) list; + object_items_nullable: (string * Yojson.Safe.t) list; +} [@@deriving yojson, show ];; + +let create () : t = { + integer_prop = None; + number_prop = None; + boolean_prop = None; + string_prop = None; + date_prop = None; + datetime_prop = None; + array_nullable_prop = []; + array_and_items_nullable_prop = []; + array_items_nullable = []; + object_nullable_prop = []; + object_and_items_nullable_prop = []; + object_items_nullable = []; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/number_only.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/number_only.ml new file mode 100644 index 00000000000..db1cefc7ef1 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/number_only.ml @@ -0,0 +1,15 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + just_number: float option; +} [@@deriving yojson, show ];; + +let create () : t = { + just_number = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/order.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/order.ml new file mode 100644 index 00000000000..b2325d39c1e --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/order.ml @@ -0,0 +1,26 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + id: int64 option; + pet_id: int64 option; + quantity: int32 option; + ship_date: string option; + (* Order Status *) + status: Enums.status option; + complete: bool option; +} [@@deriving yojson, show ];; + +let create () : t = { + id = None; + pet_id = None; + quantity = None; + ship_date = None; + status = None; + complete = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/outer_composite.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/outer_composite.ml new file mode 100644 index 00000000000..82aa40fedd8 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/outer_composite.ml @@ -0,0 +1,19 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + my_number: float option; + my_string: string option; + my_boolean: bool option; +} [@@deriving yojson, show ];; + +let create () : t = { + my_number = None; + my_string = None; + my_boolean = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/pet.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/pet.ml new file mode 100644 index 00000000000..05a7481357c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/pet.ml @@ -0,0 +1,26 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + id: int64 option; + category: Category.t option; + name: string; + photo_urls: string list; + tags: Tag.t list; + (* pet status in the store *) + status: Enums.pet_status option; +} [@@deriving yojson, show ];; + +let create (name : string) (photo_urls : string list) : t = { + id = None; + category = None; + name = name; + photo_urls = photo_urls; + tags = []; + status = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/read_only_first.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/read_only_first.ml new file mode 100644 index 00000000000..c44891ba066 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/read_only_first.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + bar: string option; + baz: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + bar = None; + baz = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/return.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/return.ml new file mode 100644 index 00000000000..73f59b66e3c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/return.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + * Schema Return.t : Model for testing reserved words + *) + +type t = { + return: int32 option; +} [@@deriving yojson, show ];; + +(** Model for testing reserved words *) +let create () : t = { + return = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/tag.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/tag.ml new file mode 100644 index 00000000000..00f8072ef9c --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/tag.ml @@ -0,0 +1,17 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + id: int64 option; + name: string option; +} [@@deriving yojson, show ];; + +let create () : t = { + id = None; + name = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/models/user.ml b/samples/openapi3/client/petstore/ocaml-client/src/models/user.ml new file mode 100644 index 00000000000..2791779acad --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/models/user.ml @@ -0,0 +1,30 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type t = { + id: int64 option; + username: string option; + first_name: string option; + last_name: string option; + email: string option; + password: string option; + phone: string option; + (* User Status *) + user_status: int32 option; +} [@@deriving yojson, show ];; + +let create () : t = { + id = None; + username = None; + first_name = None; + last_name = None; + email = None; + password = None; + phone = None; + user_status = None; +} + diff --git a/samples/openapi3/client/petstore/ocaml-client/src/support/enums.ml b/samples/openapi3/client/petstore/ocaml-client/src/support/enums.ml new file mode 100644 index 00000000000..13e0e6d0064 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/support/enums.ml @@ -0,0 +1,142 @@ +(* + * This file has been generated by the OCamlClientCodegen generator for openapi-generator. + * + * Generated by: https://openapi-generator.tech + * + *) + +type outerenuminteger = [ +| `_0 [@printer fun fmt _ -> Format.pp_print_string fmt "0"] [@name "0"] +| `_1 [@printer fun fmt _ -> Format.pp_print_string fmt "1"] [@name "1"] +| `_2 [@printer fun fmt _ -> Format.pp_print_string fmt "2"] [@name "2"] +] [@@deriving yojson, show { with_path = false }];; + +let outerenuminteger_of_yojson json = outerenuminteger_of_yojson (`List [json]) +let outerenuminteger_to_yojson e = + match outerenuminteger_to_yojson e with + | `List [json] -> json + | json -> json + +type status = [ +| `Placed [@printer fun fmt _ -> Format.pp_print_string fmt "placed"] [@name "placed"] +| `Approved [@printer fun fmt _ -> Format.pp_print_string fmt "approved"] [@name "approved"] +| `Delivered [@printer fun fmt _ -> Format.pp_print_string fmt "delivered"] [@name "delivered"] +] [@@deriving yojson, show { with_path = false }];; + +let status_of_yojson json = status_of_yojson (`List [json]) +let status_to_yojson e = + match status_to_yojson e with + | `List [json] -> json + | json -> json + +type inline_object_2_enum_form_string_array = [ +| `Greater_Than [@printer fun fmt _ -> Format.pp_print_string fmt ">"] [@name ">"] +| `Dollar [@printer fun fmt _ -> Format.pp_print_string fmt "$"] [@name "$"] +] [@@deriving yojson, show { with_path = false }];; + +let inline_object_2_enum_form_string_array_of_yojson json = inline_object_2_enum_form_string_array_of_yojson (`List [json]) +let inline_object_2_enum_form_string_array_to_yojson e = + match inline_object_2_enum_form_string_array_to_yojson e with + | `List [json] -> json + | json -> json + +type enum_query_integer = [ +| `_1 [@printer fun fmt _ -> Format.pp_print_string fmt "1"] [@name "1"] +| `Minus2 [@printer fun fmt _ -> Format.pp_print_string fmt "-2"] [@name "-2"] +] [@@deriving yojson, show { with_path = false }];; + +let enum_query_integer_of_yojson json = enum_query_integer_of_yojson (`List [json]) +let enum_query_integer_to_yojson e = + match enum_query_integer_to_yojson e with + | `List [json] -> json + | json -> json + +type enum_number = [ +| `_1Period1 [@printer fun fmt _ -> Format.pp_print_string fmt "1.1"] [@name "1.1"] +| `Minus1Period2 [@printer fun fmt _ -> Format.pp_print_string fmt "-1.2"] [@name "-1.2"] +] [@@deriving yojson, show { with_path = false }];; + +let enum_number_of_yojson json = enum_number_of_yojson (`List [json]) +let enum_number_to_yojson e = + match enum_number_to_yojson e with + | `List [json] -> json + | json -> json + +type maptest_map_of_enum_string = [ +| `UPPER [@printer fun fmt _ -> Format.pp_print_string fmt "UPPER"] [@name "UPPER"] +| `Lower [@printer fun fmt _ -> Format.pp_print_string fmt "lower"] [@name "lower"] +] [@@deriving yojson, show { with_path = false }];; + +let maptest_map_of_enum_string_of_yojson json = maptest_map_of_enum_string_of_yojson (`List [json]) +let maptest_map_of_enum_string_to_yojson e = + match maptest_map_of_enum_string_to_yojson e with + | `List [json] -> json + | json -> json + +type enum_integer = [ +| `_1 [@printer fun fmt _ -> Format.pp_print_string fmt "1"] [@name "1"] +| `Minus1 [@printer fun fmt _ -> Format.pp_print_string fmt "-1"] [@name "-1"] +] [@@deriving yojson, show { with_path = false }];; + +let enum_integer_of_yojson json = enum_integer_of_yojson (`List [json]) +let enum_integer_to_yojson e = + match enum_integer_to_yojson e with + | `List [json] -> json + | json -> json + +type just_symbol = [ +| `Greater_ThanEqual [@printer fun fmt _ -> Format.pp_print_string fmt ">="] [@name ">="] +| `Dollar [@printer fun fmt _ -> Format.pp_print_string fmt "$"] [@name "$"] +] [@@deriving yojson, show { with_path = false }];; + +let just_symbol_of_yojson json = just_symbol_of_yojson (`List [json]) +let just_symbol_to_yojson e = + match just_symbol_to_yojson e with + | `List [json] -> json + | json -> json + +type enumarrays_array_enum = [ +| `Fish [@printer fun fmt _ -> Format.pp_print_string fmt "fish"] [@name "fish"] +| `Crab [@printer fun fmt _ -> Format.pp_print_string fmt "crab"] [@name "crab"] +] [@@deriving yojson, show { with_path = false }];; + +let enumarrays_array_enum_of_yojson json = enumarrays_array_enum_of_yojson (`List [json]) +let enumarrays_array_enum_to_yojson e = + match enumarrays_array_enum_to_yojson e with + | `List [json] -> json + | json -> json + +type pet_status = [ +| `Available [@printer fun fmt _ -> Format.pp_print_string fmt "available"] [@name "available"] +| `Pending [@printer fun fmt _ -> Format.pp_print_string fmt "pending"] [@name "pending"] +| `Sold [@printer fun fmt _ -> Format.pp_print_string fmt "sold"] [@name "sold"] +] [@@deriving yojson, show { with_path = false }];; + +let pet_status_of_yojson json = pet_status_of_yojson (`List [json]) +let pet_status_to_yojson e = + match pet_status_to_yojson e with + | `List [json] -> json + | json -> json + +type enumclass = [ +| `Underscoreabc [@printer fun fmt _ -> Format.pp_print_string fmt "_abc"] [@name "_abc"] +| `Minusefg [@printer fun fmt _ -> Format.pp_print_string fmt "-efg"] [@name "-efg"] +| `Left_ParenthesisxyzRight_Parenthesis [@printer fun fmt _ -> Format.pp_print_string fmt "(xyz)"] [@name "(xyz)"] +] [@@deriving yojson, show { with_path = false }];; + +let enumclass_of_yojson json = enumclass_of_yojson (`List [json]) +let enumclass_to_yojson e = + match enumclass_to_yojson e with + | `List [json] -> json + | json -> json + +type enum_string = [ +| `UPPER [@printer fun fmt _ -> Format.pp_print_string fmt "UPPER"] [@name "UPPER"] +| `Lower [@printer fun fmt _ -> Format.pp_print_string fmt "lower"] [@name "lower"] +] [@@deriving yojson, show { with_path = false }];; + +let enum_string_of_yojson json = enum_string_of_yojson (`List [json]) +let enum_string_to_yojson e = + match enum_string_to_yojson e with + | `List [json] -> json + | json -> json diff --git a/samples/openapi3/client/petstore/ocaml-client/src/support/jsonSupport.ml b/samples/openapi3/client/petstore/ocaml-client/src/support/jsonSupport.ml new file mode 100644 index 00000000000..4b0fac77545 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/support/jsonSupport.ml @@ -0,0 +1,55 @@ +open Ppx_deriving_yojson_runtime + +let unwrap to_json json = + match to_json json with + | Result.Ok json -> json + | Result.Error s -> failwith s + +let to_int json = + match json with + | `Int x -> x + | `Intlit s -> int_of_string s + | _ -> failwith "JsonSupport.to_int" + +let to_bool json = + match json with + | `Bool x -> x + | _ -> failwith "JsonSupport.to_bool" + +let to_float json = + match json with + | `Float x -> x + | _ -> failwith "JsonSupport.to_float" + +let to_string json = + match json with + | `String s -> s + | _ -> failwith "JsonSupport.to_string" + +let to_int32 json : int32 = + match json with + | `Int x -> Int32.of_int x + | `Intlit s -> Int32.of_string s + | _ -> failwith "JsonSupport.to_int32" + +let to_int64 json : int64 = + match json with + | `Int x -> Int64.of_int x + | `Intlit s -> Int64.of_string s + | _ -> failwith "JsonSupport.to_int64" + +let of_int x = `Int x + +let of_bool b = `Bool b + +let of_float x = `Float x + +let of_string s = `String s + +let of_int32 x = `Intlit (Int32.to_string x) + +let of_int64 x = `Intlit (Int64.to_string x) + +let of_list_of of_f l = `List (List.map of_f l) + +let of_map_of of_f l = `Assoc (List.map (fun (k, v) -> (k, of_f v)) l) \ No newline at end of file diff --git a/samples/openapi3/client/petstore/ocaml-client/src/support/request.ml b/samples/openapi3/client/petstore/ocaml-client/src/support/request.ml new file mode 100644 index 00000000000..5f864b36583 --- /dev/null +++ b/samples/openapi3/client/petstore/ocaml-client/src/support/request.ml @@ -0,0 +1,39 @@ +let base_url = "http://petstore.swagger.io:80/v2" +let default_headers = Cohttp.Header.init_with "Content-Type" "application/json" + +let build_uri operation_path = Uri.of_string (base_url ^ operation_path) +let write_json_body to_json payload = + to_json payload |> Yojson.Safe.to_string ~std:true |> Cohttp_lwt.Body.of_string + +let read_json_body body = + Lwt.(Cohttp_lwt.Body.to_string body >|= Yojson.Safe.from_string) + +let read_json_body_as of_json body = + Lwt.(read_json_body body >|= of_json) + +let read_json_body_as_list body = + Lwt.(read_json_body body >|= Yojson.Safe.Util.to_list) + +let read_json_body_as_list_of of_json body = + Lwt.(read_json_body_as_list body >|= List.map of_json) + +let read_json_body_as_map_of of_json body = + Lwt.(read_json_body body >|= Yojson.Safe.Util.to_assoc >|= List.map (fun (s, v) -> (s, of_json v))) + +let replace_path_param uri param_name param_value = + let regexp = Str.regexp (Str.quote ("{" ^ param_name ^ "}")) in + let path = Str.global_replace regexp param_value (Uri.path uri) in + Uri.with_path uri path + +let init_form_encoded_body () = "" + +let add_form_encoded_body_param params (paramName, paramValue) = + let new_param_enc = Printf.sprintf {|%s=%s|} (Uri.pct_encode paramName) (Uri.pct_encode paramValue) in + if params = "" + then new_param_enc + else Printf.sprintf {|%s&%s|} params new_param_enc + +let add_form_encoded_body_params params (paramName, new_params) = + add_form_encoded_body_param params (paramName, String.concat "," new_params) + +let finalize_form_encoded_body body = Cohttp_lwt.Body.of_string body \ No newline at end of file