mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2026-03-15 23:09:08 +00:00
[OCaml][Fix] Unreferenced enum + Direct recursive types (#23005)
* [OCaml] Fix bugs around enum parsing Problem: The OCaml client generator threw IllegalArgumentException: Unreferenced enum when encountering enums inside composed schemas (anyOf/allOf/oneOf). Root Causes: 1. The enum collection logic didn't traverse into composed schemas 2. The enum hashing used order-dependent string concatenation, causing lookups to fail when enum values appeared in different orders 3. Enums directly within composed schema branches (not in properties) weren't collected Solution: 1. Added composed schema support: - New `collectEnumSchemasFromComposed()` method handles `anyOf/allOf/oneOf` - New `collectEnumSchemasFromList()` method recursively processes composed schema branches - Enums directly in composed schemas (not just in properties) are now collected 2. Refactored enum hashing to use Set: - Changed from comma-joined strings to `TreeSet<String>` for order-independent, collision-free hashing - Handles edge cases like empty string enums `""` 3. Added test case: - Tests enums in nested composed schemas - Tests enum with empty string value in anyOf * OCaml: Add support for direct recursive types * OCaml: Fix enums in anyOf * OCaml: fix recursive types * Fix recursion tests * Fix recursive types, improve tests * [OCaml] Improve title of generated README.md
This commit is contained in:
8
.github/workflows/samples-ocaml.yaml
vendored
8
.github/workflows/samples-ocaml.yaml
vendored
@@ -7,12 +7,16 @@ on:
|
||||
- 'samples/client/petstore/ocaml-fake-petstore/**'
|
||||
- 'samples/client/petstore/ocaml-oneOf-primitive/**'
|
||||
- 'samples/client/petstore/ocaml-additional-properties/**'
|
||||
- 'samples/client/petstore/ocaml-enum-in-composed-schema/**'
|
||||
- 'samples/client/petstore/ocaml-recursion-test/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'samples/client/petstore/ocaml/**'
|
||||
- 'samples/client/petstore/ocaml-fake-petstore/**'
|
||||
- 'samples/client/petstore/ocaml-oneOf-primitive/**'
|
||||
- 'samples/client/petstore/ocaml-additional-properties/**'
|
||||
- 'samples/client/petstore/ocaml-enum-in-composed-schema/**'
|
||||
- 'samples/client/petstore/ocaml-recursion-test/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -26,12 +30,14 @@ jobs:
|
||||
- 'samples/client/petstore/ocaml-fake-petstore/'
|
||||
- 'samples/client/petstore/ocaml-oneOf-primitive/'
|
||||
- 'samples/client/petstore/ocaml-additional-properties/'
|
||||
- 'samples/client/petstore/ocaml-enum-in-composed-schema/'
|
||||
- 'samples/client/petstore/ocaml-recursion-test/'
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set-up OCaml
|
||||
uses: ocaml/setup-ocaml@v3
|
||||
with:
|
||||
ocaml-compiler: 5
|
||||
ocaml-compiler: 5.3
|
||||
- name: Install
|
||||
run: opam install . --deps-only --with-test
|
||||
working-directory: ${{ matrix.sample }}
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -304,6 +304,8 @@ samples/client/petstore/ocaml/_build/
|
||||
samples/client/petstore/ocaml-fake-petstore/_build/
|
||||
samples/client/petstore/ocaml-oneOf-primitive/_build/
|
||||
samples/client/petstore/ocaml-additional-properties/_build/
|
||||
samples/client/petstore/ocaml-enum-in-composed-schema/_build/
|
||||
samples/client/petstore/ocaml-recursion-test/_build/
|
||||
|
||||
# jetbrain http client
|
||||
samples/client/jetbrains/adyen/checkout71/http/client/Apis/http-client.private.env.json
|
||||
|
||||
6
bin/configs/ocaml-enum-in-composed-schema.yaml
Normal file
6
bin/configs/ocaml-enum-in-composed-schema.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
generatorName: ocaml
|
||||
outputDir: samples/client/petstore/ocaml-enum-in-composed-schema
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/ocaml/enum-in-composed-schema.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/ocaml
|
||||
additionalProperties:
|
||||
packageName: petstore_client
|
||||
6
bin/configs/ocaml-recursion-test.yaml
Normal file
6
bin/configs/ocaml-recursion-test.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
generatorName: ocaml
|
||||
outputDir: samples/client/petstore/ocaml-recursion-test
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/ocaml/direct-recursion.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/ocaml
|
||||
additionalProperties:
|
||||
packageName: recursion_test
|
||||
@@ -11,7 +11,7 @@ title: Documentation for the ocaml Generator
|
||||
| generator type | CLIENT | |
|
||||
| generator language | OCaml | |
|
||||
| generator default templating engine | mustache | |
|
||||
| helpTxt | Generates an OCaml client library (beta). | |
|
||||
| helpTxt | Generates an OCaml client library. | |
|
||||
|
||||
## CONFIG OPTIONS
|
||||
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
|
||||
|
||||
@@ -51,16 +51,18 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
static final String X_MODEL_MODULE = "x-model-module";
|
||||
|
||||
@Setter protected String packageName = "openapi";
|
||||
@Setter protected String packageVersion = "1.0.0";
|
||||
@Setter
|
||||
protected String packageName = "openapi";
|
||||
@Setter
|
||||
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<String, List<String>> enumNames = new HashMap<>();
|
||||
private Map<String, Schema> enumHash = new HashMap<>();
|
||||
private Map<String, String> enumUniqNames;
|
||||
private Map<Set<String>, List<String>> enumNames = new HashMap<>();
|
||||
private Map<Set<String>, Schema> enumHash = new HashMap<>();
|
||||
private Map<Set<String>, String> enumUniqNames;
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
@@ -74,7 +76,7 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates an OCaml client library (beta).";
|
||||
return "Generates an OCaml client library.";
|
||||
}
|
||||
|
||||
public OCamlClientCodegen() {
|
||||
@@ -233,6 +235,105 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add support for direct recursive types (e.g., A -> A).
|
||||
* This does *not* support mutually recursive types (e.g., A -> B -> A), as this is a much more complex beast in OCaml (since mutually recursive types must live in the same file).
|
||||
*/
|
||||
@Override
|
||||
public ModelsMap postProcessModels(ModelsMap objs) {
|
||||
objs = super.postProcessModels(objs);
|
||||
|
||||
for (ModelMap mo : objs.getModels()) {
|
||||
CodegenModel cm = mo.getModel();
|
||||
|
||||
// Check if any property is a self-reference
|
||||
boolean hasSelfRef = cm.allVars.stream()
|
||||
.anyMatch(prop -> prop.isSelfReference);
|
||||
|
||||
if (hasSelfRef) {
|
||||
// Collect names of self-referencing properties
|
||||
Set<String> selfRefPropNames = cm.allVars.stream()
|
||||
.filter(p -> p.isSelfReference)
|
||||
.map(p -> p.name)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// The property lists (vars, allVars, etc.) contain DIFFERENT objects
|
||||
// Match by name since isSelfReference might only be set in allVars
|
||||
List<List<CodegenProperty>> allPropertyLists = Arrays.asList(
|
||||
cm.allVars, cm.vars, cm.requiredVars, cm.optionalVars,
|
||||
cm.readOnlyVars, cm.readWriteVars, cm.parentVars
|
||||
);
|
||||
|
||||
for (List<CodegenProperty> propList : allPropertyLists) {
|
||||
for (CodegenProperty prop : propList) {
|
||||
if (selfRefPropNames.contains(prop.name)) {
|
||||
if (prop.isContainer && prop.items != null) {
|
||||
// For containers, update items and reconstruct the container type
|
||||
prop.items.dataType = "t";
|
||||
prop.items.datatypeWithEnum = "t";
|
||||
if (prop.items.baseType != null) {
|
||||
prop.items.baseType = "t";
|
||||
}
|
||||
if (prop.items.complexType != null) {
|
||||
prop.items.complexType = "t";
|
||||
}
|
||||
|
||||
// Reconstruct the container type based on the updated items
|
||||
if (prop.isArray) {
|
||||
prop.dataType = "t list";
|
||||
prop.datatypeWithEnum = "t list";
|
||||
} else if (prop.isMap) {
|
||||
prop.dataType = "(string * t) list";
|
||||
prop.datatypeWithEnum = "(string * t) list";
|
||||
}
|
||||
} else {
|
||||
// For non-containers, just replace the type directly
|
||||
prop.dataType = "t";
|
||||
prop.datatypeWithEnum = "t";
|
||||
}
|
||||
|
||||
// Update baseType and complexType for all cases
|
||||
if (prop.baseType != null) {
|
||||
prop.baseType = "t";
|
||||
}
|
||||
if (prop.complexType != null) {
|
||||
prop.complexType = "t";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fix enum references in composed schemas (anyOf, oneOf, allOf)
|
||||
if (cm.getComposedSchemas() != null) {
|
||||
fixEnumReferencesInComposedSchemas(cm.getComposedSchemas().getAnyOf());
|
||||
fixEnumReferencesInComposedSchemas(cm.getComposedSchemas().getOneOf());
|
||||
fixEnumReferencesInComposedSchemas(cm.getComposedSchemas().getAllOf());
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
private void fixEnumReferencesInComposedSchemas(List<CodegenProperty> schemas) {
|
||||
if (schemas == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (CodegenProperty schema : schemas) {
|
||||
// If this schema is an enum, add Enums. prefix to datatypeWithEnum
|
||||
if (schema.isEnum) {
|
||||
if (!schema.datatypeWithEnum.startsWith("Enums.")) {
|
||||
schema.datatypeWithEnum = "Enums." + schema.datatypeWithEnum;
|
||||
}
|
||||
// Also update dataType for the variant constructor
|
||||
if (!schema.dataType.startsWith("Enums.")) {
|
||||
schema.dataType = "Enums." + schema.dataType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void enrichPropertiesWithEnumDefaultValues(List<CodegenProperty> properties) {
|
||||
for (CodegenProperty property : properties) {
|
||||
if (property.get_enum() != null && property.get_enum().size() == 1) {
|
||||
@@ -276,8 +377,10 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private String hashEnum(Schema schema) {
|
||||
return ((List<Object>) schema.getEnum()).stream().map(String::valueOf).collect(Collectors.joining(","));
|
||||
private Set<String> hashEnum(Schema schema) {
|
||||
return ((List<Object>) schema.getEnum()).stream()
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
private boolean isEnumSchema(Schema schema) {
|
||||
@@ -290,7 +393,7 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
} else if (ModelUtils.isMapSchema(schema) && schema.getAdditionalProperties() instanceof Schema) {
|
||||
collectEnumSchemas(parentName, sName, (Schema) schema.getAdditionalProperties());
|
||||
} else if (isEnumSchema(schema)) {
|
||||
String h = hashEnum(schema);
|
||||
Set<String> h = hashEnum(schema);
|
||||
if (!enumHash.containsKey(h)) {
|
||||
enumHash.put(h, schema);
|
||||
enumNames.computeIfAbsent(h, k -> new ArrayList<>()).add(sName.toLowerCase(Locale.ROOT));
|
||||
@@ -299,6 +402,8 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: Composed schemas (anyOf, allOf, oneOf) are handled in the Map-based method
|
||||
// via collectEnumSchemasFromComposed() which properly processes their structure
|
||||
}
|
||||
|
||||
private void collectEnumSchemas(String sName, Schema schema) {
|
||||
@@ -327,6 +432,47 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
collectEnumSchemas(pName, ModelUtils.getSchemaItems(schema));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle composed schemas (anyOf, allOf, oneOf) - recursively process their structure
|
||||
collectEnumSchemasFromComposed(pName, schema);
|
||||
}
|
||||
}
|
||||
|
||||
private void collectEnumSchemasFromComposed(String parentName, Schema schema) {
|
||||
if (schema.getAnyOf() != null) {
|
||||
collectEnumSchemasFromList(parentName, schema.getAnyOf());
|
||||
}
|
||||
|
||||
if (schema.getAllOf() != null) {
|
||||
collectEnumSchemasFromList(parentName, schema.getAllOf());
|
||||
}
|
||||
|
||||
if (schema.getOneOf() != null) {
|
||||
collectEnumSchemasFromList(parentName, schema.getOneOf());
|
||||
}
|
||||
}
|
||||
|
||||
private void collectEnumSchemasFromList(String parentName, List<Schema> schemas) {
|
||||
int index = 0;
|
||||
for (Schema composedSchema : schemas) {
|
||||
// Check if the composed schema itself is an enum
|
||||
if (isEnumSchema(composedSchema)) {
|
||||
String enumName = composedSchema.getName() != null ? composedSchema.getName() : "any_of_" + index;
|
||||
collectEnumSchemas(parentName, enumName, composedSchema);
|
||||
}
|
||||
|
||||
if (composedSchema.getProperties() != null) {
|
||||
collectEnumSchemas(parentName, composedSchema.getProperties());
|
||||
}
|
||||
if (composedSchema.getAdditionalProperties() != null && composedSchema.getAdditionalProperties() instanceof Schema) {
|
||||
collectEnumSchemas(parentName, composedSchema.getName(), (Schema) composedSchema.getAdditionalProperties());
|
||||
}
|
||||
if (ModelUtils.isArraySchema(composedSchema) && ModelUtils.getSchemaItems(composedSchema) != null) {
|
||||
collectEnumSchemas(parentName, composedSchema.getName(), ModelUtils.getSchemaItems(composedSchema));
|
||||
}
|
||||
// Recursively handle nested composed schemas
|
||||
collectEnumSchemasFromComposed(parentName, composedSchema);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,8 +524,8 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
|
||||
private void computeEnumUniqNames() {
|
||||
Map<String, String> definitiveNames = new HashMap<>();
|
||||
for (String h : enumNames.keySet()) {
|
||||
Map<String, Set<String>> definitiveNames = new HashMap<>();
|
||||
for (Set<String> h : enumNames.keySet()) {
|
||||
boolean hasDefName = false;
|
||||
List<String> nameCandidates = enumNames.get(h);
|
||||
for (String name : nameCandidates) {
|
||||
@@ -600,13 +746,13 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
String prefix = inner.getEnum() != null ? "Enums." : "";
|
||||
return "(string * " + prefix + getTypeDeclaration(inner) + ") list";
|
||||
} else if (p.getEnum() != null) {
|
||||
String h = hashEnum(p);
|
||||
Set<String> h = hashEnum(p);
|
||||
return enumUniqNames.get(h);
|
||||
}
|
||||
|
||||
Schema referencedSchema = ModelUtils.getReferencedSchema(openAPI, p);
|
||||
if (referencedSchema != null && referencedSchema.getEnum() != null) {
|
||||
String h = hashEnum(referencedSchema);
|
||||
Set<String> h = hashEnum(referencedSchema);
|
||||
return "Enums." + enumUniqNames.get(h);
|
||||
}
|
||||
|
||||
@@ -739,8 +885,8 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> e : enumUniqNames.entrySet()) {
|
||||
allModels.add(buildEnumModelWrapper(e.getValue(), e.getKey()));
|
||||
for (Map.Entry<Set<String>, String> e : enumUniqNames.entrySet()) {
|
||||
allModels.add(buildEnumModelWrapper(e.getValue(), String.join(",", e.getKey())));
|
||||
}
|
||||
|
||||
enumUniqNames.clear();
|
||||
@@ -770,7 +916,7 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
String hash = String.join(",", property.get_enum());
|
||||
Set<String> hash = new TreeSet<>(property.get_enum());
|
||||
|
||||
if (enumUniqNames.containsKey(hash)) {
|
||||
return enumUniqNames.get(hash);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# {{{projectName}}}
|
||||
# OCaml API client for {{{packageName}}}
|
||||
{{#appDescriptionWithNewLines}}
|
||||
{{{.}}}
|
||||
{{/appDescriptionWithNewLines}}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
description: |
|
||||
Test for direct recursive types in OCaml generator.
|
||||
|
||||
This spec only tests direct recursion (A -> A) and NOT mutual recursion (A -> B -> A).
|
||||
|
||||
The OCaml generator does not support mutual recursion because OCaml requires mutually
|
||||
recursive types to be declared together in the same file using "type a = ... and b = ..."
|
||||
syntax. The generator's architecture uses one model per file, making this infeasible.
|
||||
|
||||
Note: The generic test file modules/openapi-generator/src/test/resources/3_0/recursion.yaml
|
||||
contains both Foo (direct recursion) and Bar/Baz (mutual recursion), which is why we
|
||||
cannot use it for OCaml testing.
|
||||
version: 1.0.0
|
||||
title: OCaml Direct Recursion Test
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
ArrayRecursion:
|
||||
type: object
|
||||
description: Test recursive type within an array (optional)
|
||||
properties:
|
||||
value:
|
||||
type: integer
|
||||
format: int32
|
||||
children:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ArrayRecursion'
|
||||
required:
|
||||
- value
|
||||
|
||||
DirectRecursion:
|
||||
type: object
|
||||
description: Test direct self-reference (not in container, optional)
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
next:
|
||||
$ref: '#/components/schemas/DirectRecursion'
|
||||
required:
|
||||
- id
|
||||
|
||||
MapRecursion:
|
||||
type: object
|
||||
description: Test recursive type within a map (optional)
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
childMap:
|
||||
type: object
|
||||
additionalProperties:
|
||||
$ref: '#/components/schemas/MapRecursion'
|
||||
required:
|
||||
- name
|
||||
|
||||
RequiredRecursion:
|
||||
type: object
|
||||
description: Test required self-reference field
|
||||
properties:
|
||||
value:
|
||||
type: string
|
||||
parent:
|
||||
$ref: '#/components/schemas/RequiredRecursion'
|
||||
required:
|
||||
- value
|
||||
- parent
|
||||
|
||||
RequiredArrayRecursion:
|
||||
type: object
|
||||
description: Test required array of self-references
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
siblings:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RequiredArrayRecursion'
|
||||
required:
|
||||
- id
|
||||
- siblings
|
||||
|
||||
MultipleRecursiveFields:
|
||||
type: object
|
||||
description: Test multiple recursive fields in the same model
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
left:
|
||||
$ref: '#/components/schemas/MultipleRecursiveFields'
|
||||
right:
|
||||
$ref: '#/components/schemas/MultipleRecursiveFields'
|
||||
children:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/MultipleRecursiveFields'
|
||||
required:
|
||||
- name
|
||||
@@ -0,0 +1,49 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Test Enum in Composed Schema
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/test:
|
||||
get:
|
||||
operationId: getTest
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TestModel'
|
||||
components:
|
||||
schemas:
|
||||
TestModel:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
config:
|
||||
anyOf:
|
||||
- allOf:
|
||||
- type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- type1
|
||||
- type2
|
||||
- type3
|
||||
options:
|
||||
type: object
|
||||
properties:
|
||||
value:
|
||||
type: string
|
||||
enum:
|
||||
- value1
|
||||
- value2
|
||||
- value3
|
||||
optionalUrl:
|
||||
anyOf:
|
||||
- type: string
|
||||
format: uri
|
||||
- type: string
|
||||
enum:
|
||||
- ""
|
||||
@@ -1,4 +1,4 @@
|
||||
#
|
||||
# OCaml API client for petstore_client
|
||||
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
|
||||
This OCaml package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
version=0.27.0
|
||||
ocaml-version=4.14.0
|
||||
@@ -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
|
||||
@@ -0,0 +1,14 @@
|
||||
.ocamlformat
|
||||
README.md
|
||||
dune
|
||||
dune-project
|
||||
petstore_client.opam
|
||||
src/apis/default_api.ml
|
||||
src/apis/default_api.mli
|
||||
src/models/test_model.ml
|
||||
src/models/test_model_config.ml
|
||||
src/models/test_model_config_all_of_options.ml
|
||||
src/models/test_model_optional_url.ml
|
||||
src/support/enums.ml
|
||||
src/support/jsonSupport.ml
|
||||
src/support/request.ml
|
||||
@@ -0,0 +1 @@
|
||||
7.21.0-SNAPSHOT
|
||||
@@ -0,0 +1,33 @@
|
||||
# OCaml API client for petstore_client
|
||||
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
|
||||
This OCaml package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 1.0.0
|
||||
- Package version: 1.0.0
|
||||
- Generator version: 7.21.0-SNAPSHOT
|
||||
- Build package: org.openapitools.codegen.languages.OCamlClientCodegen
|
||||
|
||||
## Requirements.
|
||||
|
||||
OCaml 5.x
|
||||
|
||||
## Installation
|
||||
|
||||
Please run the following commands to build the package `petstore_client`:
|
||||
|
||||
```sh
|
||||
opam install . --deps-only --with-test
|
||||
eval $(opam env)
|
||||
dune build
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
The generated directory structure is:
|
||||
- `src/apis`: contains several modules, each with several functions. Each function is an API endpoint.
|
||||
- `src/models`: contains several modules. Each module contains:
|
||||
- a type `t` representing an input and/or output schema of the OpenAPI spec
|
||||
- a smart constructor `create` for this type
|
||||
- `src/support`: various modules used by the generated APIs and Models
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
(lang dune 2.0)
|
||||
(name petstore_client)
|
||||
@@ -0,0 +1,25 @@
|
||||
opam-version: "2.0"
|
||||
name: "petstore_client"
|
||||
version: "1.0.0"
|
||||
synopsis: ""
|
||||
description: """
|
||||
Longer description
|
||||
"""
|
||||
maintainer: "Name <email>"
|
||||
authors: "Name <email>"
|
||||
license: ""
|
||||
homepage: ""
|
||||
bug-reports: ""
|
||||
dev-repo: ""
|
||||
depends: [
|
||||
"ocaml"
|
||||
"ocamlfind"
|
||||
"ocamlformat" {= "0.27.0"}
|
||||
"dune"
|
||||
"ppx_deriving_yojson"
|
||||
"conf-libev"
|
||||
"lwt"
|
||||
"cohttp-lwt-unix" {< "6.0.0"}
|
||||
"cohttp-async" {< "6.0.0"}
|
||||
]
|
||||
build: ["dune" "build" "-p" name]
|
||||
@@ -0,0 +1,14 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
|
||||
let get_test () =
|
||||
let open Lwt.Infix in
|
||||
let uri = Request.build_uri "/test" in
|
||||
let headers = Request.default_headers in
|
||||
Cohttp_lwt_unix.Client.call `GET uri ~headers >>= fun (resp, body) ->
|
||||
Request.read_json_body_as (JsonSupport.unwrap Test_model.of_yojson) resp body
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
|
||||
val get_test : unit -> Test_model.t Lwt.t
|
||||
@@ -0,0 +1,38 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
name: string
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
; [@key "name"]
|
||||
config: Test_model_config.t
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
; [@key "config"]
|
||||
optional_url: Test_model_optional_url.t
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
; [@key "optionalUrl"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
let create () : t = {
|
||||
name = None;
|
||||
config = None;
|
||||
optional_url = None;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
_type: Enums.testmodel_config_type
|
||||
option [@default
|
||||
|
||||
None
|
||||
]
|
||||
; [@key "type"]
|
||||
options: Test_model_config_all_of_options.t
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
; [@key "options"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
let create () : t = {
|
||||
_type = None;
|
||||
options = None;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
value: Enums.value
|
||||
option [@default
|
||||
|
||||
None
|
||||
]
|
||||
; [@key "value"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
let create () : t = {
|
||||
value = None;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
type t =
|
||||
| AnyOf0 of string
|
||||
| AnyOf1 of Enums.any_of_1
|
||||
[@@deriving show, eq];;
|
||||
|
||||
let to_yojson = function
|
||||
| AnyOf0 v -> [%to_yojson: string] v
|
||||
| AnyOf1 v -> [%to_yojson: Enums.any_of_1] v
|
||||
|
||||
(* Manual implementations because the derived one encodes into a tuple list where the first element is the constructor name. *)
|
||||
|
||||
let of_yojson json =
|
||||
[
|
||||
[%of_yojson: string] json
|
||||
|> Stdlib.Result.to_option
|
||||
|> Stdlib.Option.map (fun v -> AnyOf0 v);
|
||||
[%of_yojson: Enums.any_of_1] json
|
||||
|> Stdlib.Result.to_option
|
||||
|> Stdlib.Option.map (fun v -> AnyOf1 v);
|
||||
]
|
||||
|> Stdlib.List.filter_map (Fun.id)
|
||||
|> function
|
||||
| t :: _ -> Ok t (* Return the first successful parsing. *)
|
||||
| [] -> Error ("Failed to parse JSON " ^ Yojson.Safe.show json ^ " into a value of type Test_model_optional_url.t")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
|
||||
type any_of_1 = [
|
||||
| `Empty [@printer fun fmt _ -> Format.pp_print_string fmt "empty"] [@name "empty"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let any_of_1_of_yojson json = any_of_1_of_yojson (`List [json])
|
||||
let any_of_1_to_yojson e =
|
||||
match any_of_1_to_yojson e with
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
|
||||
type value = [
|
||||
| `Value1 [@printer fun fmt _ -> Format.pp_print_string fmt "value1"] [@name "value1"]
|
||||
| `Value2 [@printer fun fmt _ -> Format.pp_print_string fmt "value2"] [@name "value2"]
|
||||
| `Value3 [@printer fun fmt _ -> Format.pp_print_string fmt "value3"] [@name "value3"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let value_of_yojson json = value_of_yojson (`List [json])
|
||||
let value_to_yojson e =
|
||||
match value_to_yojson e with
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
|
||||
type testmodel_config_type = [
|
||||
| `Type1 [@printer fun fmt _ -> Format.pp_print_string fmt "type1"] [@name "type1"]
|
||||
| `Type2 [@printer fun fmt _ -> Format.pp_print_string fmt "type2"] [@name "type2"]
|
||||
| `Type3 [@printer fun fmt _ -> Format.pp_print_string fmt "type3"] [@name "type3"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let testmodel_config_type_of_yojson json = testmodel_config_type_of_yojson (`List [json])
|
||||
let testmodel_config_type_to_yojson e =
|
||||
match testmodel_config_type_to_yojson e with
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
@@ -0,0 +1,68 @@
|
||||
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 (Stdlib.List.map of_f l)
|
||||
|
||||
let of_map_of of_f l = `Assoc (Stdlib.List.map (fun (k, v) -> (k, of_f v)) l)
|
||||
|
||||
let to_map_of of_f json =
|
||||
match json with
|
||||
| `Assoc l ->
|
||||
Stdlib.List.fold_right
|
||||
(fun (k, json) acc ->
|
||||
match (of_f json, acc) with
|
||||
| Stdlib.Result.Ok parsed_v, Stdlib.Result.Ok tl ->
|
||||
Stdlib.Result.Ok ((k, parsed_v) :: tl)
|
||||
| Stdlib.Result.Error e, _ -> Stdlib.Result.Error e
|
||||
| _, Stdlib.Result.Error e -> Stdlib.Result.Error e)
|
||||
l (Stdlib.Result.Ok [])
|
||||
| _ -> Stdlib.Result.Error "Expected"
|
||||
@@ -0,0 +1,110 @@
|
||||
let api_key = ""
|
||||
let base_url = "http://localhost"
|
||||
let default_headers = Cohttp.Header.init_with "Content-Type" "application/json"
|
||||
|
||||
let option_fold f default o =
|
||||
match o with
|
||||
| Some v -> f v
|
||||
| None -> default
|
||||
|
||||
let build_uri operation_path = Uri.of_string (base_url ^ operation_path)
|
||||
|
||||
let add_string_header headers key value =
|
||||
Cohttp.Header.add headers key value
|
||||
|
||||
let add_string_header_multi headers key values =
|
||||
Cohttp.Header.add_multi headers key values
|
||||
|
||||
let add_header headers key to_string value =
|
||||
Cohttp.Header.add headers key (to_string value)
|
||||
|
||||
let add_header_multi headers key to_string value =
|
||||
Cohttp.Header.add_multi headers key (to_string value)
|
||||
|
||||
let maybe_add_header headers key to_string value =
|
||||
option_fold (add_header headers key to_string) headers value
|
||||
|
||||
let maybe_add_header_multi headers key to_string value =
|
||||
option_fold (add_header_multi headers key to_string) headers value
|
||||
|
||||
let write_string_body s = Cohttp_lwt.Body.of_string s
|
||||
|
||||
let write_json_body payload =
|
||||
Cohttp_lwt.Body.of_string (Yojson.Safe.to_string payload ~std:true)
|
||||
|
||||
let write_as_json_body to_json payload = write_json_body (to_json payload)
|
||||
|
||||
let handle_response resp on_success_handler =
|
||||
match Cohttp.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 >|= Stdlib.List.map of_json)
|
||||
|
||||
let read_json_body_as_map resp body =
|
||||
Lwt.(read_json_body resp body >|= Yojson.Safe.Util.to_assoc)
|
||||
|
||||
let read_json_body_as_map_of of_json resp body =
|
||||
Lwt.(read_json_body_as_map resp body >|= Stdlib.List.map (fun (s, v) -> (s, of_json v)))
|
||||
|
||||
let replace_string_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.pct_decode (Uri.path uri)) in
|
||||
Uri.with_path uri path
|
||||
|
||||
let replace_path_param uri param_name to_string param_value =
|
||||
replace_string_path_param uri param_name (to_string param_value)
|
||||
|
||||
let maybe_replace_path_param uri param_name to_string param_value =
|
||||
option_fold (replace_path_param uri param_name to_string) uri param_value
|
||||
|
||||
let add_query_param uri param_name to_string param_value =
|
||||
Uri.add_query_param' uri (param_name, to_string param_value)
|
||||
|
||||
let add_query_param_list uri param_name to_string param_value =
|
||||
Uri.add_query_param uri (param_name, to_string param_value)
|
||||
|
||||
let maybe_add_query_param uri param_name to_string param_value =
|
||||
option_fold (add_query_param uri param_name to_string) uri param_value
|
||||
|
||||
(** Corresponds to:
|
||||
- [style = form]
|
||||
- [explode = true]
|
||||
- type [object]
|
||||
|
||||
See https://swagger.io/docs/specification/v3_0/serialization/#query-parameters
|
||||
*)
|
||||
let add_query_param_exploded_form_object uri _param_name to_string param_value =
|
||||
Stdlib.List.fold_left
|
||||
(fun uri (param_name, param_value) -> add_query_param uri param_name to_string param_value)
|
||||
uri
|
||||
param_value
|
||||
|
||||
let init_form_encoded_body () = ""
|
||||
|
||||
let add_form_encoded_body_param params param_name to_string param_value =
|
||||
let new_param_enc = Printf.sprintf {|%s=%s|} (Uri.pct_encode param_name) (Uri.pct_encode (to_string param_value)) in
|
||||
if params = ""
|
||||
then new_param_enc
|
||||
else Printf.sprintf {|%s&%s|} params new_param_enc
|
||||
|
||||
let add_form_encoded_body_param_list params param_name to_string new_params =
|
||||
add_form_encoded_body_param params param_name (String.concat ",") (to_string new_params)
|
||||
|
||||
let maybe_add_form_encoded_body_param params param_name to_string param_value =
|
||||
option_fold (add_form_encoded_body_param params param_name to_string) params param_value
|
||||
|
||||
let finalize_form_encoded_body body = Cohttp_lwt.Body.of_string body
|
||||
@@ -1,4 +1,4 @@
|
||||
#
|
||||
# OCaml API client for petstore_client
|
||||
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \'' \\
|
||||
|
||||
This OCaml package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
@@ -68,7 +68,7 @@ let find_pets_by_status ~status =
|
||||
let open Lwt.Infix in
|
||||
let uri = Request.build_uri "/pet/findByStatus" in
|
||||
let headers = Request.default_headers in
|
||||
let uri = Request.add_query_param_list uri "status" (Stdlib.List.map Enums.show_status
|
||||
let uri = Request.add_query_param_list uri "status" (Stdlib.List.map Enums.show_pet_status
|
||||
|
||||
)
|
||||
status in
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
val add_pet : pet_t:Pet.t -> unit Lwt.t
|
||||
val delete_pet : pet_id:int64 -> ?api_key:string -> unit -> unit Lwt.t
|
||||
val find_pets_by_status : status:Enums.status list -> Pet.t list Lwt.t
|
||||
val find_pets_by_status : status:Enums.pet_status list -> Pet.t list Lwt.t
|
||||
val find_pets_by_tags : tags:string list -> Pet.t list Lwt.t
|
||||
val get_pet_by_id : pet_id:int64 -> Pet.t Lwt.t
|
||||
val update_pet : pet_t:Pet.t -> unit Lwt.t
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
None
|
||||
]
|
||||
; [@key "enum_number"]
|
||||
outer_enum: Enums.order_status
|
||||
outer_enum: Enums.status
|
||||
|
||||
option [@default None]
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
|
||||
; [@key "outerEnumInteger"]
|
||||
outer_enum_default_value: Enums.order_status
|
||||
outer_enum_default_value: Enums.status
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
|
||||
; [@key "shipDate"]
|
||||
status: Enums.order_status
|
||||
status: Enums.status
|
||||
option [@default
|
||||
|
||||
None
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
[@default []]
|
||||
|
||||
; [@key "tags"]
|
||||
status: Enums.status
|
||||
status: Enums.pet_status
|
||||
option [@default
|
||||
|
||||
None
|
||||
|
||||
@@ -5,101 +5,9 @@
|
||||
*
|
||||
*)
|
||||
|
||||
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 }, eq];;
|
||||
|
||||
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 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 }, eq];;
|
||||
|
||||
let map_of_enum_string_of_yojson json = map_of_enum_string_of_yojson (`List [json])
|
||||
let map_of_enum_string_to_yojson e =
|
||||
match 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 }, eq];;
|
||||
|
||||
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 }, eq];;
|
||||
|
||||
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 enumclass = [
|
||||
| `_abc [@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 }, eq];;
|
||||
|
||||
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 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 }, eq];;
|
||||
|
||||
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 order_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 }, eq];;
|
||||
|
||||
let order_status_of_yojson json = order_status_of_yojson (`List [json])
|
||||
let order_status_to_yojson e =
|
||||
match order_status_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 }, eq];;
|
||||
|
||||
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_form_string_array = [
|
||||
| `Greater_Than [@printer fun fmt _ -> Format.pp_print_string fmt ">"] [@name ">"]
|
||||
| `Dollar [@printer fun fmt _ -> Format.pp_print_string fmt "$"] [@name "$"]
|
||||
| `Greater_Than [@printer fun fmt _ -> Format.pp_print_string fmt ">"] [@name ">"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let enum_form_string_array_of_yojson json = enum_form_string_array_of_yojson (`List [json])
|
||||
@@ -108,35 +16,14 @@ let enum_form_string_array_to_yojson e =
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
|
||||
type parentwithnullable_type = [
|
||||
| `ChildWithNullable [@printer fun fmt _ -> Format.pp_print_string fmt "ChildWithNullable"] [@name "ChildWithNullable"]
|
||||
type just_symbol = [
|
||||
| `Dollar [@printer fun fmt _ -> Format.pp_print_string fmt "$"] [@name "$"]
|
||||
| `Greater_ThanEqual [@printer fun fmt _ -> Format.pp_print_string fmt ">="] [@name ">="]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let parentwithnullable_type_of_yojson json = parentwithnullable_type_of_yojson (`List [json])
|
||||
let parentwithnullable_type_to_yojson e =
|
||||
match parentwithnullable_type_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 }, eq];;
|
||||
|
||||
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 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 }, eq];;
|
||||
|
||||
let array_enum_of_yojson json = array_enum_of_yojson (`List [json])
|
||||
let array_enum_to_yojson e =
|
||||
match array_enum_to_yojson e with
|
||||
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
|
||||
|
||||
@@ -151,7 +38,109 @@ let singlereftype_to_yojson e =
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
|
||||
type enum_number = [
|
||||
| `Minus1Period2 [@printer fun fmt _ -> Format.pp_print_string fmt "-1.2"] [@name "-1.2"]
|
||||
| `_1Period1 [@printer fun fmt _ -> Format.pp_print_string fmt "1.1"] [@name "1.1"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
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 status = [
|
||||
| `Approved [@printer fun fmt _ -> Format.pp_print_string fmt "approved"] [@name "approved"]
|
||||
| `Delivered [@printer fun fmt _ -> Format.pp_print_string fmt "delivered"] [@name "delivered"]
|
||||
| `Placed [@printer fun fmt _ -> Format.pp_print_string fmt "placed"] [@name "placed"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
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 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 }, eq];;
|
||||
|
||||
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 enum_integer = [
|
||||
| `Minus1 [@printer fun fmt _ -> Format.pp_print_string fmt "-1"] [@name "-1"]
|
||||
| `_1 [@printer fun fmt _ -> Format.pp_print_string fmt "1"] [@name "1"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
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 enum_query_integer = [
|
||||
| `Minus2 [@printer fun fmt _ -> Format.pp_print_string fmt "-2"] [@name "-2"]
|
||||
| `_1 [@printer fun fmt _ -> Format.pp_print_string fmt "1"] [@name "1"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
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 array_enum = [
|
||||
| `Crab [@printer fun fmt _ -> Format.pp_print_string fmt "crab"] [@name "crab"]
|
||||
| `Fish [@printer fun fmt _ -> Format.pp_print_string fmt "fish"] [@name "fish"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let array_enum_of_yojson json = array_enum_of_yojson (`List [json])
|
||||
let array_enum_to_yojson e =
|
||||
match array_enum_to_yojson e with
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
|
||||
type parentwithnullable_type = [
|
||||
| `ChildWithNullable [@printer fun fmt _ -> Format.pp_print_string fmt "ChildWithNullable"] [@name "ChildWithNullable"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let parentwithnullable_type_of_yojson json = parentwithnullable_type_of_yojson (`List [json])
|
||||
let parentwithnullable_type_to_yojson e =
|
||||
match parentwithnullable_type_to_yojson e with
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
|
||||
type 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 }, eq];;
|
||||
|
||||
let map_of_enum_string_of_yojson json = map_of_enum_string_of_yojson (`List [json])
|
||||
let map_of_enum_string_to_yojson e =
|
||||
match map_of_enum_string_to_yojson e with
|
||||
| `List [json] -> json
|
||||
| json -> json
|
||||
|
||||
type enumclass = [
|
||||
| `Left_ParenthesisxyzRight_Parenthesis [@printer fun fmt _ -> Format.pp_print_string fmt "(xyz)"] [@name "(xyz)"]
|
||||
| `Minusefg [@printer fun fmt _ -> Format.pp_print_string fmt "-efg"] [@name "-efg"]
|
||||
| `_abc [@printer fun fmt _ -> Format.pp_print_string fmt "_abc"] [@name "_abc"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
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 = [
|
||||
| `Empty [@printer fun fmt _ -> Format.pp_print_string fmt "empty"] [@name "empty"]
|
||||
| `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 }, eq];;
|
||||
@@ -161,3 +150,15 @@ let enum_string_to_yojson e =
|
||||
match enum_string_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 }, eq];;
|
||||
|
||||
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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#
|
||||
# OCaml API client for petstore_client
|
||||
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
|
||||
This OCaml package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
version=0.27.0
|
||||
ocaml-version=4.14.0
|
||||
@@ -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
|
||||
@@ -0,0 +1,14 @@
|
||||
.ocamlformat
|
||||
README.md
|
||||
dune
|
||||
dune-project
|
||||
recursion_test.opam
|
||||
src/models/array_recursion.ml
|
||||
src/models/direct_recursion.ml
|
||||
src/models/map_recursion.ml
|
||||
src/models/multiple_recursive_fields.ml
|
||||
src/models/required_array_recursion.ml
|
||||
src/models/required_recursion.ml
|
||||
src/support/enums.ml
|
||||
src/support/jsonSupport.ml
|
||||
src/support/request.ml
|
||||
@@ -0,0 +1 @@
|
||||
7.21.0-SNAPSHOT
|
||||
44
samples/client/petstore/ocaml-recursion-test/README.md
Normal file
44
samples/client/petstore/ocaml-recursion-test/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# OCaml API client for recursion_test
|
||||
Test for direct recursive types in OCaml generator.
|
||||
|
||||
This spec only tests direct recursion (A -> A) and NOT mutual recursion (A -> B -> A).
|
||||
|
||||
The OCaml generator does not support mutual recursion because OCaml requires mutually
|
||||
recursive types to be declared together in the same file using \''type a = ... and b = ...\''
|
||||
syntax. The generator's architecture uses one model per file, making this infeasible.
|
||||
|
||||
Note: The generic test file modules/openapi-generator/src/test/resources/3_0/recursion.yaml
|
||||
contains both Foo (direct recursion) and Bar/Baz (mutual recursion), which is why we
|
||||
cannot use it for OCaml testing.
|
||||
|
||||
|
||||
This OCaml package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 1.0.0
|
||||
- Package version: 1.0.0
|
||||
- Generator version: 7.21.0-SNAPSHOT
|
||||
- Build package: org.openapitools.codegen.languages.OCamlClientCodegen
|
||||
|
||||
## Requirements.
|
||||
|
||||
OCaml 5.x
|
||||
|
||||
## Installation
|
||||
|
||||
Please run the following commands to build the package `recursion_test`:
|
||||
|
||||
```sh
|
||||
opam install . --deps-only --with-test
|
||||
eval $(opam env)
|
||||
dune build
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
The generated directory structure is:
|
||||
- `src/apis`: contains several modules, each with several functions. Each function is an API endpoint.
|
||||
- `src/models`: contains several modules. Each module contains:
|
||||
- a type `t` representing an input and/or output schema of the OpenAPI spec
|
||||
- a smart constructor `create` for this type
|
||||
- `src/support`: various modules used by the generated APIs and Models
|
||||
|
||||
9
samples/client/petstore/ocaml-recursion-test/dune
Normal file
9
samples/client/petstore/ocaml-recursion-test/dune
Normal file
@@ -0,0 +1,9 @@
|
||||
(include_subdirs unqualified)
|
||||
(library
|
||||
(name recursion_test)
|
||||
(public_name recursion_test)
|
||||
(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)
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
(lang dune 2.0)
|
||||
(name recursion_test)
|
||||
@@ -0,0 +1,25 @@
|
||||
opam-version: "2.0"
|
||||
name: "recursion_test"
|
||||
version: "1.0.0"
|
||||
synopsis: ""
|
||||
description: """
|
||||
Longer description
|
||||
"""
|
||||
maintainer: "Name <email>"
|
||||
authors: "Name <email>"
|
||||
license: ""
|
||||
homepage: ""
|
||||
bug-reports: ""
|
||||
dev-repo: ""
|
||||
depends: [
|
||||
"ocaml"
|
||||
"ocamlfind"
|
||||
"ocamlformat" {= "0.27.0"}
|
||||
"dune"
|
||||
"ppx_deriving_yojson"
|
||||
"conf-libev"
|
||||
"lwt"
|
||||
"cohttp-lwt-unix" {< "6.0.0"}
|
||||
"cohttp-async" {< "6.0.0"}
|
||||
]
|
||||
build: ["dune" "build" "-p" name]
|
||||
@@ -0,0 +1,31 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
* Schema Array_recursion.t : Test recursive type within an array (optional)
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
value: int32
|
||||
|
||||
|
||||
|
||||
|
||||
; [@key "value"]
|
||||
children: t list
|
||||
[@default []]
|
||||
|
||||
; [@key "children"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
(** Test recursive type within an array (optional) *)
|
||||
let create (value : int32) : t = {
|
||||
value = value;
|
||||
children = [];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
* Schema Direct_recursion.t : Test direct self-reference (not in container, optional)
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
id: string
|
||||
|
||||
|
||||
|
||||
|
||||
; [@key "id"]
|
||||
next: t
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
; [@key "next"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
(** Test direct self-reference (not in container, optional) *)
|
||||
let create (id : string) : t = {
|
||||
id = id;
|
||||
next = None;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
* Schema Map_recursion.t : Test recursive type within a map (optional)
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
name: string
|
||||
|
||||
|
||||
|
||||
|
||||
; [@key "name"]
|
||||
child_map: (string * t) list
|
||||
|
||||
[@default []] [@to_yojson JsonSupport.of_map_of [%to_yojson: t]] [@of_yojson JsonSupport.to_map_of [%of_yojson: t]]
|
||||
; [@key "childMap"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
(** Test recursive type within a map (optional) *)
|
||||
let create (name : string) : t = {
|
||||
name = name;
|
||||
child_map = [];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
* Schema Multiple_recursive_fields.t : Test multiple recursive fields in the same model
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
name: string
|
||||
|
||||
|
||||
|
||||
|
||||
; [@key "name"]
|
||||
left: t
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
; [@key "left"]
|
||||
right: t
|
||||
|
||||
option [@default None]
|
||||
|
||||
|
||||
; [@key "right"]
|
||||
children: t list
|
||||
[@default []]
|
||||
|
||||
; [@key "children"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
(** Test multiple recursive fields in the same model *)
|
||||
let create (name : string) : t = {
|
||||
name = name;
|
||||
left = None;
|
||||
right = None;
|
||||
children = [];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
* Schema Required_array_recursion.t : Test required array of self-references
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
id: int32
|
||||
|
||||
|
||||
|
||||
|
||||
; [@key "id"]
|
||||
siblings: t list
|
||||
|
||||
|
||||
; [@key "siblings"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
(** Test required array of self-references *)
|
||||
let create (id : int32) (siblings : t list) : t = {
|
||||
id = id;
|
||||
siblings = siblings;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
* Schema Required_recursion.t : Test required self-reference field
|
||||
*)
|
||||
|
||||
|
||||
|
||||
|
||||
type t = {
|
||||
value: string
|
||||
|
||||
|
||||
|
||||
|
||||
; [@key "value"]
|
||||
parent: t
|
||||
|
||||
|
||||
|
||||
|
||||
; [@key "parent"]
|
||||
} [@@deriving yojson { strict = false }, show, eq ];;
|
||||
|
||||
(** Test required self-reference field *)
|
||||
let create (value : string) (parent : t) : t = {
|
||||
value = value;
|
||||
parent = parent;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
(*
|
||||
* This file has been generated by the OCamlClientCodegen generator for openapi-generator.
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*
|
||||
*)
|
||||
@@ -0,0 +1,68 @@
|
||||
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 (Stdlib.List.map of_f l)
|
||||
|
||||
let of_map_of of_f l = `Assoc (Stdlib.List.map (fun (k, v) -> (k, of_f v)) l)
|
||||
|
||||
let to_map_of of_f json =
|
||||
match json with
|
||||
| `Assoc l ->
|
||||
Stdlib.List.fold_right
|
||||
(fun (k, json) acc ->
|
||||
match (of_f json, acc) with
|
||||
| Stdlib.Result.Ok parsed_v, Stdlib.Result.Ok tl ->
|
||||
Stdlib.Result.Ok ((k, parsed_v) :: tl)
|
||||
| Stdlib.Result.Error e, _ -> Stdlib.Result.Error e
|
||||
| _, Stdlib.Result.Error e -> Stdlib.Result.Error e)
|
||||
l (Stdlib.Result.Ok [])
|
||||
| _ -> Stdlib.Result.Error "Expected"
|
||||
@@ -0,0 +1,110 @@
|
||||
let api_key = ""
|
||||
let base_url = "http://localhost"
|
||||
let default_headers = Cohttp.Header.init_with "Content-Type" "application/json"
|
||||
|
||||
let option_fold f default o =
|
||||
match o with
|
||||
| Some v -> f v
|
||||
| None -> default
|
||||
|
||||
let build_uri operation_path = Uri.of_string (base_url ^ operation_path)
|
||||
|
||||
let add_string_header headers key value =
|
||||
Cohttp.Header.add headers key value
|
||||
|
||||
let add_string_header_multi headers key values =
|
||||
Cohttp.Header.add_multi headers key values
|
||||
|
||||
let add_header headers key to_string value =
|
||||
Cohttp.Header.add headers key (to_string value)
|
||||
|
||||
let add_header_multi headers key to_string value =
|
||||
Cohttp.Header.add_multi headers key (to_string value)
|
||||
|
||||
let maybe_add_header headers key to_string value =
|
||||
option_fold (add_header headers key to_string) headers value
|
||||
|
||||
let maybe_add_header_multi headers key to_string value =
|
||||
option_fold (add_header_multi headers key to_string) headers value
|
||||
|
||||
let write_string_body s = Cohttp_lwt.Body.of_string s
|
||||
|
||||
let write_json_body payload =
|
||||
Cohttp_lwt.Body.of_string (Yojson.Safe.to_string payload ~std:true)
|
||||
|
||||
let write_as_json_body to_json payload = write_json_body (to_json payload)
|
||||
|
||||
let handle_response resp on_success_handler =
|
||||
match Cohttp.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 >|= Stdlib.List.map of_json)
|
||||
|
||||
let read_json_body_as_map resp body =
|
||||
Lwt.(read_json_body resp body >|= Yojson.Safe.Util.to_assoc)
|
||||
|
||||
let read_json_body_as_map_of of_json resp body =
|
||||
Lwt.(read_json_body_as_map resp body >|= Stdlib.List.map (fun (s, v) -> (s, of_json v)))
|
||||
|
||||
let replace_string_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.pct_decode (Uri.path uri)) in
|
||||
Uri.with_path uri path
|
||||
|
||||
let replace_path_param uri param_name to_string param_value =
|
||||
replace_string_path_param uri param_name (to_string param_value)
|
||||
|
||||
let maybe_replace_path_param uri param_name to_string param_value =
|
||||
option_fold (replace_path_param uri param_name to_string) uri param_value
|
||||
|
||||
let add_query_param uri param_name to_string param_value =
|
||||
Uri.add_query_param' uri (param_name, to_string param_value)
|
||||
|
||||
let add_query_param_list uri param_name to_string param_value =
|
||||
Uri.add_query_param uri (param_name, to_string param_value)
|
||||
|
||||
let maybe_add_query_param uri param_name to_string param_value =
|
||||
option_fold (add_query_param uri param_name to_string) uri param_value
|
||||
|
||||
(** Corresponds to:
|
||||
- [style = form]
|
||||
- [explode = true]
|
||||
- type [object]
|
||||
|
||||
See https://swagger.io/docs/specification/v3_0/serialization/#query-parameters
|
||||
*)
|
||||
let add_query_param_exploded_form_object uri _param_name to_string param_value =
|
||||
Stdlib.List.fold_left
|
||||
(fun uri (param_name, param_value) -> add_query_param uri param_name to_string param_value)
|
||||
uri
|
||||
param_value
|
||||
|
||||
let init_form_encoded_body () = ""
|
||||
|
||||
let add_form_encoded_body_param params param_name to_string param_value =
|
||||
let new_param_enc = Printf.sprintf {|%s=%s|} (Uri.pct_encode param_name) (Uri.pct_encode (to_string param_value)) in
|
||||
if params = ""
|
||||
then new_param_enc
|
||||
else Printf.sprintf {|%s&%s|} params new_param_enc
|
||||
|
||||
let add_form_encoded_body_param_list params param_name to_string new_params =
|
||||
add_form_encoded_body_param params param_name (String.concat ",") (to_string new_params)
|
||||
|
||||
let maybe_add_form_encoded_body_param params param_name to_string param_value =
|
||||
option_fold (add_form_encoded_body_param params param_name to_string) params param_value
|
||||
|
||||
let finalize_form_encoded_body body = Cohttp_lwt.Body.of_string body
|
||||
@@ -1,4 +1,4 @@
|
||||
#
|
||||
# OCaml API client for petstore_client
|
||||
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
|
||||
This OCaml package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
*)
|
||||
|
||||
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"]
|
||||
| `Placed [@printer fun fmt _ -> Format.pp_print_string fmt "placed"] [@name "placed"]
|
||||
] [@@deriving yojson, show { with_path = false }, eq];;
|
||||
|
||||
let status_of_yojson json = status_of_yojson (`List [json])
|
||||
|
||||
Reference in New Issue
Block a user