MCPcopy Index your code
hub / github.com/CourseOrchestra/hurdy-gurdy

github.com/CourseOrchestra/hurdy-gurdy @2.10

Chat with this repo
repository ↗ · DeepWiki ↗ · release 2.10 ↗ · + Follow
209 symbols 565 edges 25 files 17 documented · 8%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Actions Status: build

Maven Central Version

Hurdy-Gurdy

Generates client and server side Java/Kotlin code based on OpenAPI spec, using swagger-parser, JavaPoet and KotlinPoet.

Usage example (as Maven plugin)

<plugin>
    <groupId>ru.curs</groupId>
    <artifactId>hurdy-gurdy</artifactId>
    <version>2.10</version>
    <configuration>

        <rootPackage>com.example.project</rootPackage>
        <spec>${basedir}/src/main/openapi/api.yaml</spec>

        <generateResponseParameter>true</generateResponseParameter>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>gen-server</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Usage example (in Kotlin code, e.g. Gradle's buildSrc)

import ru.curs.hurdygurdy.KotlinCodegen
import ru.curs.hurdygurdy.GeneratorParams

val codegen = KotlinCodegen(GeneratorParams.rootPackage("com.example.project"))
val yamlPath = project.layout.projectDirectory.asFile.toPath().resolve("src/main/openapi/api.yaml")
val resultPath = project.layout.buildDirectory.get().asFile.toPath().resolve("generated-sources")
Files.createDirectories(resultPath)
codegen.generate(yamlPath, resultPath)

Configuration parameters

Parameter name Type Default value Description
rootPackage String Sets the root package for all the generated classes. Controller and Api interfaces will be generated in controller subpackage, and all the DTOs will be generated in dto subpackage.
generateResponseParameter boolean false Set to true if you need to have HttpServletResponse parameter in each generated Controller method. You might need this in order to return specific HTTP status codes. When used together with the operation-level extension x-include-request: true, the generated method will also include jakarta.servlet.http.HttpServletRequest request parameter.
generateApiInterface boolean false Set to true if you need to generate an interface called Api besides Controller. Api methods do not have HttpServletResponse parameter.
forceSnakeCaseForProperties boolean true By default, hurdy-gurdy expects all the properties of DTO classes to be defined in snake_case in the specification. It converts these names to camelCase for generated classes and sets Jackson's SnakeCaseStrategy so that they will still be snake_case in JSON representation. If you don't want this (e. g. if you want your properties to be defined in camelCase everywhere) you can turn off this function via this parameter.

Inheritance hierarchy compatible with openapi-codegen

components:
  schemas:
    #---------------------------------------------------------------------------
    # Abstract class with discriminator 'vehicle_type'
    #---------------------------------------------------------------------------
    'Vehicle':
      type: object
      nullable: false
      properties:
        'vehicle_type':
          type: string
      discriminator:
        propertyName: vehicle_type
        mapping:
          'CAR': '#/components/schemas/Car'
          'TRUCK': '#/components/schemas/Truck'
    #---------------------------------------------------------------------------
    # Concrete classes
    #---------------------------------------------------------------------------
    'Car':
      nullable: false
      allOf:
        - $ref: "#/components/schemas/Vehicle"
        - type: object
          properties:
            'car_property':
              type: string
    'Truck':
      nullable: false
      allOf:
        - $ref: "#/components/schemas/Vehicle"
        - type: object
          properties:
            'truck_property':
              type: string

This will produce the following in Java:

//Vehicle.java
@Data
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "vehicle_type"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = Car.class, name = "CAR"),
        @JsonSubTypes.Type(value = Truck.class, name = "TRUCK")})
public class Vehicle {
}

//Car.java
@Data
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class Car extends Vehicle {
    private String carProperty;
}

This will produce the following in Kotlin:

//Vehicle.kt
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy::class)
@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY,
  property = "vehicle_type"
)
@JsonSubTypes(JsonSubTypes.Type(value = Car::class, name = "CAR"),
JsonSubTypes.Type(value = Truck::class, name = "TRUCK"))
public sealed class Vehicle()

//Car.kt
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy::class)
public data class Car(
    public val carProperty: String? = null
) : Vehicle()

Make DTO classes implement interfaces

You can use x-extends extended property on schema element in order to make DTO implement given interface or interfaces:

components:
  schemas:
    MenuItemDTO:
      type: object
      nullable: false
      x-extends:
        - java.lang.Serializable
      title: MenuItemDTO
      properties:
        [....]

References to external specifications

You can use references to external specification files if they are available on the same file system as the original one. However, hurdy-gurdy does not attempt to generate code for referenced specifications: we believe this should be done explicitly for every spec. Hurdy-gurdy just uses x-package extension property on the referenced specification in order to define the location of referenced DTOs.

For example, given the following spec fragment:

  /api/v1/external:
    get:
      operationId: external
      responses:
        "200":
          description: external file
          content:
            text/csv:
              schema:
                $ref: 'externalfile.yaml#/components/schemas/DatabaseConnectionRequest'

The externalfile.yaml file should be located in the same folder and it should contain x-package property:

openapi: 3.0.1
info:
paths:
x-package: com.example

Then code generator will suggest that com.example.dto.DatabaseConnectionRequest class exists on the classpath.

Extension points exported contracts — how you extend this code

TypeSpecExtractor (Interface)
(no doc) [2 implementers]
src/main/java/ru/curs/hurdygurdy/TypeSpecExtractor.java
TypeProducersFactory (Interface)
(no doc) [2 implementers]
src/main/java/ru/curs/hurdygurdy/TypeProducersFactory.java

Core symbols most depended-on inside this repo

builder
called by 73
src/main/java/ru/curs/hurdygurdy/APIExtractor.java
generate
called by 35
src/main/java/ru/curs/hurdygurdy/Codegen.java
snakeToCamel
called by 18
src/main/java/ru/curs/hurdygurdy/CaseUtils.java
pathToCamel
called by 10
src/main/java/ru/curs/hurdygurdy/CaseUtils.java
rootPackage
called by 9
src/main/java/ru/curs/hurdygurdy/GeneratorParams.java
kebabToCamel
called by 8
src/main/java/ru/curs/hurdygurdy/CaseUtils.java
defineJavaType
called by 7
src/main/java/ru/curs/hurdygurdy/JavaTypeDefiner.java
generateResponseParameter
called by 7
src/main/java/ru/curs/hurdygurdy/GeneratorParams.java

Shape

Method 180
Class 26
Interface 2
Enum 1

Languages

Java90%
Kotlin10%

Modules by API surface

src/test/java/ru/curs/hurdygurdy/KCodegenTest.java22 symbols
src/test/java/ru/curs/hurdygurdy/CaseUtilsTest.java21 symbols
src/test/java/ru/curs/hurdygurdy/GeneratedCodeCompiler.java18 symbols
src/test/java/ru/curs/hurdygurdy/CodegenTest.java18 symbols
src/main/java/ru/curs/hurdygurdy/TypeDefiner.java17 symbols
src/main/java/ru/curs/hurdygurdy/KotlinTypeDefiner.kt14 symbols
src/main/java/ru/curs/hurdygurdy/JavaTypeDefiner.java10 symbols
src/main/java/ru/curs/hurdygurdy/JavaAPIExtractor.java10 symbols
src/main/java/ru/curs/hurdygurdy/GeneratorParams.java10 symbols
src/main/java/ru/curs/hurdygurdy/APIExtractor.java9 symbols
src/main/java/ru/curs/hurdygurdy/CaseUtils.java7 symbols
src/main/java/ru/curs/hurdygurdy/KotlinAPIExtractor.kt6 symbols

Datastores touched

postgresDatabase · 1 repos

For agents

$ claude mcp add hurdy-gurdy \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact