Openapi to Rescript generator
Note This is just a first pass at this. Some stuff isn't supported yet. Expect some bugs.
Introduction:
-
Generate rescript code from an openapi spec document to help you validate & parse responses from your api. It also generates types for parameters and validation for request bodies.
-
It supports openapi specs in json and yaml form.
-
Most of the heavy lifting is done by the Rescript Struct and Rescript Json Schema libs.
Usage:
- Install via
npm install openapi-to-rescript-generator -g
- Run
openapi-to-rescript --inputFile <inputFilePath> --outputFile <outputFilePath>
.- Example:
openapi-to-rescript --inputFile ./foo/openapi.json --outputFile ./bar/output.res
- Example:
- You will then need to install rescript struct in your app for working with the file you created.
Limitations
- Needs an operationId to be specified
- The validation structs are only generated for responses and request bodies.
- Parameters are just generated as types and have no validation.
- We only support string enums for parameters at the moment
- You may need to manually annotate unions in the output. See here for more details: https://github.com/DZakh/rescript-struct/issues/56
- Here is an example of annotating a union inline:
let saveLogRequestBodyStruct = S.object(o =>
{
"level": o->S.field(
"level",
(
S.union([
S.literalVariant(String("fatal"), #fatal),
S.literalVariant(String("error"), #error),
S.literalVariant(String("warn"), #warn),
S.literalVariant(String("info"), #info),
S.literalVariant(String("debug"), #debug),
S.literalVariant(String("trace"), #trace),
]): S.t<[#fatal | #error | #warn | #info | #debug | #trace]>
),
),
"service": o->S.field("service", S.string()),
}
)->S.Object.strict
-
If an enum contains a Rescript reserved keyword, we can't convert it to a polymorphic variant, so instead we just set it as a string. (I don't know of a way to alias a poly variant's name).
- e.g.
type queryParams = {state: [#open | #merged | #declined]}
becomestype queryParams = {state: string}
asopen
is a Rescript reserved keyword.
- e.g.
-
We don't do nested parameter schemas at the moment. We only do the first level of the schema. e.g.
parameters:
- name: tags
in: query
description: tags to filter by
required: false
style: form
schema:
type: array
items:
type: string
- name: limit
in: query
description: maximum number of results to return
required: false
schema:
type: integer
format: int32
will be converted to:
type queryParams = {
tags?: array,
limit?: integer,
}
Things to possibly add in the future
- Maybe going forward we could implement a full RPC library similar to trpc:
Dev:
- Use npm link for trying out while developing
- Note: we develop in esm, but bundle to cjs as I had issues of dynamically created import statements being created when i tried to bundle to esm (e.g.
import("foo" + bar + "baz")
). I think it was a library file. - Run
node bundle/index.bundle.cjs --inputFile /wherever/openapi.json --outputFile ./output.res
to run/test when developing - To publish a new version:
- First check it installs ok by running
npm run build-and-publish-dry-run
, thennpm install . -g
from the project folder and test the command works globally- If it works ok, run
npm uninstall openapi-to-rescript-generator -g
to uninstall.
- If it works ok, run
- bump the version in
package.json
- run
npm build-and-publish-dry-run
and check there are no wayward files listed. - run
npm build-and-publish
- First check it installs ok by running