-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
144 additions
and
0 deletions.
There are no files selected for viewing
144 changes: 144 additions & 0 deletions
144
...ges/documentation/src/pages/getting-started/tips-for-writing-specifications.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# Tips for writing a good specification | ||
|
||
Garbage in, garbage out applies especially to code generation tools. In short the more detailed, and accurate the | ||
specification, the better the code and documentation you'll get from it. | ||
|
||
This page outlines some tips to enhance the quality of the generated code, and make your specification easier to maintain. | ||
|
||
## Declare `operationId`s | ||
|
||
The `operationId` is used to generate method and type names. If you don't specify one, | ||
then one will be generated from the HTTP method and route. | ||
|
||
Eg: | ||
Without an operation id, you'll get generated method names, that might look like: | ||
```typescript | ||
client.getV2ListListIdItems(...) | ||
client.postV2ListListIdItems(...) | ||
``` | ||
|
||
Instead of more readable ones like: | ||
```typescript | ||
client.getTodoListItems(...) | ||
client.createTodoListItem(...) | ||
``` | ||
|
||
## Make liberal use of `$ref` | ||
|
||
Using `$ref` can reduce the repetition in your specification, making it far more readable | ||
and maintainable. | ||
|
||
It also has the advantage of giving a name to things, that can be used in the generated code, | ||
and avoid generating duplicate code. | ||
|
||
If you can't use `$ref` easily, there is also the option to [extract-inline-schemas](./concepts/extract-inline-schemas) | ||
which will generate names to avoid inline types, but it won't save you from duplicate code. | ||
|
||
Example: | ||
```yaml | ||
paths: | ||
/list: | ||
get: | ||
operationId: getTodoLists | ||
responses: | ||
200: | ||
description: 'success' | ||
content: | ||
application/json: | ||
schema: | ||
type: array | ||
items: | ||
$ref: '#/components/schemas/TodoList' | ||
components: | ||
schemas: | ||
TodoList: | ||
properties: | ||
... | ||
``` | ||
## Compose `$ref`s using `allOf` / `anyOf` | ||
You can create union and intersection types using `allOf` and `anyOf` | ||
|
||
**Union Types** | ||
Using `anyOf` we can combine types / schemas into unions. | ||
```yaml | ||
components: | ||
schemas: | ||
Apple: | ||
type: object | ||
Pear: | ||
type: object | ||
Fruit: | ||
anyOf: | ||
- $ref: "#/components/schemas/Apple" | ||
- $ref: "#/components/schemas/Pear" | ||
``` | ||
Produces something like: | ||
```typescript | ||
export type Apple = {} | ||
export type Pear = {} | ||
export type Fruit = Apple | Pear | ||
```` | ||
**Intersection Types** | ||
Using `allOf` of we can combine types / schemas into intersection types. This is often | ||
handy for "extending" a type with additional properties | ||
```yaml | ||
components: | ||
schemas: | ||
Profile: | ||
type: object | ||
properties: | ||
... | ||
FullProfile: | ||
type: object | ||
allOf: | ||
- $ref: "#/components/schemas/Profile" | ||
- type: object | ||
properties: | ||
... | ||
``` | ||
Produces something like: | ||
```typescript | ||
export type Profile = {} | ||
export type FullProfile = Profile & {} | ||
```` | ||
## Use validation constraints where sensible | ||
A fairly rich set of validations can be specified in the specification. Make use of these in order | ||
for robust runtime validation. | ||
Example: | ||
```yaml | ||
components: | ||
schemas: | ||
MyRequestBody: | ||
type: object | ||
properties: | ||
name: | ||
type: string | ||
minLength: 1 | ||
tags: | ||
type: array | ||
minItems: 1 | ||
maxItems: 100 | ||
items: | ||
type: string | ||
``` | ||
See [compatibility table](../overview/compatibility#schema-object) for an idea of what's possible. | ||
## Use a clear `info.title` | ||
|
||
The root `info.title` property is used to name the generated client. Using a name like: | ||
```yaml | ||
info: | ||
title: Awesome Service | ||
``` | ||
|
||
Will output a class `AwesomeServiceClient` | ||
|
||
If you can't modify the title, you can use `--override-specification-title "Some Other Title"` | ||
to workaround. |