Inspired by [restful-react](https://github.com/contiamo/restful-react)
orval
is able to generate axios client with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification, either in yaml
or json
formats.
Type-safe data fetchers can be generated from an OpenAPI specification using the following command:
orval import --file MY_OPENAPI_SPEC.yaml --output my-awesome-generated-types.tsx
This command can be invoked by either:
- Installing
orval
globally and running it in the terminal:npm i -g orval
, or - Adding a
script
to yourpackage.json
like so:
"scripts": {
"start": "webpack-dev-server",
"build": "webpack -p",
+ "generate-fetcher": "orval import --file MY_SWAGGER_DOCS.json --output FETCHERS.tsx"
}
Your client can then be generated by running npm run generate-fetcher
. Optionally, we recommend linting/prettifying the output for readability like so:
"scripts": {
"start": "webpack-dev-server",
"build": "webpack -p",
"generate-fetcher": "orval import --file MY_SWAGGER_DOCS.json --output FETCHERS.tsx",
+ "postgenerate-fetcher": "prettier FETCHERS.d.tsx --write"
}
To enforce the best quality as possible of specification, we have integrated the amazing OpenAPI linter from IBM. We strongly encourage you to setup your custom rules with a .validaterc
file, you can find all useful information about this configuration here.
To activate this, add a --validation
flag to your orval
call.
Adding the --github
flag to orval import
instead of using the --file
flag allows us to create your client from an OpenAPI spec remotely hosted on GitHub. (how is this real life ๐ฅ )
To generate components from remote specifications, you'll need to follow the following steps:
-
Visit your GitHub settings.
-
Click Generate New Token and choose the following:
Token Description: (enter anything) Scopes: [X] repo [X] repo:status [X] repo_deployment [X] public_repo [X] repo:invite
-
Click Generate token.
-
Copy the generated string.
-
Open a terminal and run
orval import --github username:repo:branch:path/to/openapi.yaml --output MY_FETCHERS.tsx
, substituting things where necessary. -
You will be prompted for a token.
-
Paste your token.
-
You will be asked if you'd like to save it for later. This is entirely up to you and completely safe: it is saved in your
node_modules
folder and not committed to version control or sent to us or anything: the source code of this whole thing is public so you're safe.Caveat: Since your token is stored in
node_modules
, your token will be removed on eachnpm install
oforval
. -
You're done! ๐
In some cases, you might need to augment an existing OpenAPI specification on the fly, for code-generation purposes. Our CLI makes this quite straightforward:
orval import --file myspec.yaml --output mybettercomponents.tsx --transformer path/to/my-transformer.js
The function specified in --transformer
is pure: it imports your --file
, transforms it, and passes the augmented OpenAPI specification to orval
's generator. Here's how it can be used:
// /path/to/my-transformer.js
/**
* Transformer function for orval.
*
* @param {OpenAPIObject} schema
* @return {OpenAPIObject}
*/
module.exports = inputSchema => ({
...inputSchema,
// Place your augmentations here
paths: Object.entries(schema.paths).reduce(
(mem, [path, pathItem]) => ({
...mem,
[path]: Object.entries(pathItem).reduce(
(pathItemMem, [verb, operation]) => ({
...pathItemMem,
[verb]: {
...fixOperationId(path, verb, operation)
}
}),
{}
)
}),
{}
)
});
orval
supports the concept of "schema stitching" in a RESTful ecosystem as well. We are able to tie multiple backends together and generate code using a single configuration file, orval.config.js
To activate this "advanced mode", replace all flags from your orval
call with the config flag: --config orval.config.js
(or any filename that you want).
interface RestfulClientConfig {
[backend: string]: {
output?: string;
outputFile?: string;
types?: string;
workDir?: string;
file?: string;
github?: string;
transformer?: string;
validation?: boolean;
mock?: boolean | MockOptions;
override?: OverrideOptions;
};
}
// orval.config.js
module.exports = {
'petstore-file': {
file: 'examples/petstore.yaml',
output: 'examples/petstoreFromFileSpecWithConfig.ts'
},
'petstore-file-transfomer': {
file: 'examples/petstore.yaml',
output: 'examples/petstoreFromFileSpecWithTransformer.ts',
types: 'examples/model',
transformer: 'examples/transformer-add-version.js',
override: {
operations: {
listPets: {
transformer: 'examples/transformer-response-type.js'
}
}
},
mock: {
responses: {
listPets: {
properties: () => {
return {
id: () => faker.random.number({min: 1, max: 9}),
'/tag|name/': 'jon'
};
}
},
showPetById: {
data: () => ({
id: faker.random.number({min: 1, max: 99}),
name: faker.name.firstName(),
tag: faker.helpers.randomize([faker.random.word(), undefined])
})
}
}
}
}
};
// package.json
{
"scripts": {
"gen": "orval import --config orval.config.js",
"gen-first": "orval import --config orval.config.js myFirstBackend"
}
}