Openapi-generator: [REQ] FSharp (F#) server stub based on record types

Created on 9 Mar 2019  路  19Comments  路  Source: OpenAPITools/openapi-generator

F#+Giraffe backend stub generator.

Alternatives attempted:

  • OpenAPITypeProvider: Type provider can be used both during design time (IDE) and runtime. It generates C# classes on the fly, they are composing naturally in F#. Having to reload IDE every time changes are made to the API file. Some metadata (path, info) are also exposed. It is an excellent type provider, but we could have something more composable in F#.
  • Using model classes from C# ASP.NET or NancyFX server stub: No reload issue on changes. Generates code not directly used in the F# project. It generates C# classes not composing naturally in F#.

In the above solutions classes are accessible from F# via the common platform (.NET CLI).

I suggest a new backend generating F# record types like:

type Employee = 
    { name: string
    ; salary: float 
    }

Record type would provide familiar access with dot notation, plus being accessible from C# code if needed.

These generated accessors would be composable in functional code:

type Employee with
        static member getName employee = employee.name
    static member getSalary employee = employee.salary
    static member withName value employee = {employee with name = value}
    static member withSalary value employee = {employee with salary = value}

_The updater has the object as its last parameter, which is good practice in functional programming._

Example usage:

let totalSalary = List.sum Employee.getSalary employees
let employeeCount = List.length employees
let equalSalary = totalSalary / (float employeeCount)
let equalEmployees = List.map (Employee.withSalary equalSalary) employees

Future versions of F# may gain new syntax for convenient property access, which will simplify the getter to: _.salary

Despite this the composable update functions (like withSalary) will remain useful.

I suggest using the Giraffe Web framework in the generated backend stub, since it generally results in a clean default implementation. Giraffe has a SampleApp solution which could be used as the basis of the generated one.

New generator F# help wanted

Most helpful comment

@viktor-ferenczi Sounds good to me 馃憤

Would you have time to contribute the new F# server stub generator?

We can work with you to create the new generator similar to what we've done before: https://github.com/OpenAPITools/openapi-generator/projects?query=is%3Aclosed

All 19 comments

@viktor-ferenczi Sounds good to me 馃憤

Would you have time to contribute the new F# server stub generator?

We can work with you to create the new generator similar to what we've done before: https://github.com/OpenAPITools/openapi-generator/projects?query=is%3Aclosed

That's exactly my plan. It is just good practice to add a request first and wait for some discussion, so I start in the right direction. I already have the openapi-generator project set up in IntelliJ IDEA.

_Hint needed:_ How can I limit the build to a single backend? (For development speed.)

@viktor-ferenczi when you recompile the project, use mvn clean package -DskipTests instead.

@viktor-ferenczi I'm happy to help contribute to this. Have you opened a repository anywhere?

To facilitate collaboration among F# developers, what about creating a branch "f-sharp-server" in the official OpenAPI Generator repo so that all F# developers can contribute to this branch to move the project forward?

@wing328 Sounds good to me!

@viktor-ferenczi are you at a stage where you can push to this branch? I'm starting from a clean slate, and ideally I'd prefer to avoid duplicating work that you've already done.

@nmfisher I haven't started on this yet. (High workload on my regular job.)

@viktor-ferenczi no worries. I'll create the base class and the templates so that people can start patching it to support the F# server stub generator.

No problem @viktor-ferenczi , I am working on this at the moment and aim to have something available on the f-sharp-server branch in the next few days.

@nmfisher I'll wait for your PR then.

Fork is at https://github.com/nmfisher/openapi-generator/tree/f-sharp-server if anyone wants to track WIP before issuing a PR.

@nmfisher I've just cloned your branch.

From Model.mustache:

module Model =
    type Definitions = OpenAPIV3Provider<"openapi.yaml">

Is it a placeholder?

The whole point of the fsharp-server backend is to avoid having to use OpenAPIV3Provider on the server side, since that does not play well with IDEs during development. (See ticket description above.)

Right now, it's just a placeholder.

I understand your point about IDE restarts (though that seems to be a general issue around type providers - I also experimented with a new type provider for this branch but decided not to bother).

Seems a shame to re-do all the good work that OpenAPIV3Provider has already done though?

Yeah, it is a shame.

But there is another reason: A type provider is relatively opaque, while generated source is transparent. It is possible to copy part of the generated type declarations. For example, to come up with an in-memory record containing a subset of fields. This is often useful in practice.

@nmfisher Good job on starting the backend! In case you would like me to write the template for the model record type generation, please let me know.

Thanks @viktor-ferenczi - I'm actually going through the model record template at the moment. Will let you know if I have any questions.

Thanks for the PR by @nmfisher

@viktor-ferenczi when you've time, I wonder if you can review. Thanks!

Was this page helpful?
0 / 5 - 0 ratings