-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(docs): server stub generation #3760
Closed
Closed
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
d1c5d09
docs: add a tab for server code generation
dannysheridan e0a6703
start express page
dannysheridan 73da05f
drafts of fastapi, spring, and express
dannysheridan 581adf7
remove step text
chdeskur 7e3a808
update server docs
fern-bot b1dcae0
Merge branch 'main' into dsheridan/add-server-code
chdeskur 7de679a
Update welcome.mdx
dannysheridan 4a1ab50
Update docs.yml
dannysheridan 716a46e
Merge branch 'main' into dsheridan/add-server-code
dannysheridan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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,143 @@ | ||
--- | ||
title: Express Server | ||
description: Generate Express Node.js server code from an API specification including OpenAPI, Swagger, AsyncAPI, and Fern Definition. | ||
subtite: Generate types and networking logic for your Node.js Express server. | ||
slug: express | ||
--- | ||
|
||
Express is a minimal and flexible Node.js web application framework. It is a popular choice for building APIs and web servers. | ||
|
||
Fern generates TypeScript types and networking logic for your Express server. This saves you time and adds compile-time safety by guaranteeing that you are serving the exact API that you specified in your API definition. | ||
|
||
## What Fern generates | ||
|
||
- TypeScript interfaces for your API types | ||
- Exceptions that you can throw for non-200 responses | ||
- Interfaces for you to define your business logic | ||
- All the networking/HTTP logic to call your API | ||
|
||
## Use the starter repository | ||
|
||
Clone the [starter repo](https://github.com/fern-api/express-starter/) for Express + React. | ||
|
||
## Demo video | ||
|
||
Learn how Fern can be helpful when building an Express server. | ||
|
||
<div style="position: relative; padding-bottom: 62.5%; height: 0;"><iframe src="https://www.loom.com/embed/31f4243c4d824c54938bdc4840fbb8ba?sid=3f460e48-af22-4db3-be2f-48884ab0170d" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe></div> | ||
|
||
## Getting started | ||
|
||
<Steps> | ||
|
||
### Define your API | ||
|
||
Define your API using the [OpenAPI Specification](/learn/api-definition/openapi/overview) or the [Fern Definition](/learn/api-definition/fern/overview). | ||
|
||
### Add the Express generator | ||
|
||
Add the Express server generator to your `generators.yml` file. | ||
|
||
<CodeBlock title="generators.yml"> | ||
```yaml | ||
groups: | ||
express-server: | ||
generators: | ||
- name: fernapi/fern-typescript-express | ||
version: 0.15.0 | ||
output: | ||
location: local-file-system | ||
path: ../app/server | ||
``` | ||
</CodeBlock> | ||
|
||
### | ||
Run the [CLI](/learn/cli-api/cli-reference/cli-overview) command `fern generate --group express-server`. | ||
|
||
<Note>Make sure to enable `allowSyntheticDefaultImports` in your `tsconfig.json` when using this generator.</Note> | ||
|
||
### Implement the functions | ||
|
||
Provide the business logic by implementing each function. For example, if we were implenting the IMDb API, we would implement the `get_movie` function. | ||
|
||
<CodeBlock title="src/movies_service.py"> | ||
```python | ||
from .generated.fern import AbstractMoviesService, Movie, MovieDoesNotExistError, MovieId | ||
|
||
class MoviesService(AbstractMoviesService): | ||
def get_movie(self, *, movie_id: str) -> Movie: | ||
if movie_id == "titanic": | ||
return Movie( | ||
id=MovieId.from_str("titantic"), | ||
title="Titanic", | ||
rating=9.8, | ||
) | ||
raise MovieDoesNotExistError(MovieId.from_str(movie_id)) | ||
``` | ||
</CodeBlock> | ||
|
||
### Run the server | ||
|
||
```bash | ||
poetry run start | ||
``` | ||
|
||
### Call the API 🚀 | ||
|
||
```bash | ||
$ curl --location --request GET --silent 'localhost:8080/movies/titanic' | jq . | ||
{ | ||
"id": "titantic", | ||
"title": "Titanic", | ||
"rating": 9.8 | ||
} | ||
|
||
$ curl --location --request GET --silent 'localhost:8080/movies/oceans-11' | jq . | ||
{ | ||
"error": "MovieDoesNotExistError", | ||
"errorInstanceId": "f6e1d69c-bf97-42d5-bc89-5e42773e3880", | ||
"content": "oceans-11" | ||
} | ||
``` | ||
|
||
</Steps> | ||
|
||
## Advanced Configurations | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @zachkirsch good ol' server stubs coming back into play There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lol love it. I think I have “server INTERFACES not stubs” still burned into my memory |
||
|
||
Tailor the `config` of the Express server generator to your needs. The default values for all options are `false`. | ||
|
||
| Configuration Option | Description | | ||
| -------------------- | ----------- | | ||
| `useBrandedStringAliases` | When `true`, string aliases are generated as branded strings. This makes each alias feel like its own type and improves compile-time safety. | | ||
| `areImplementationsOptional` | | | ||
| `doNotHandleUnrecognizedErrors` | | | ||
| `includeUtilsOnUnionMembers` | | | ||
| `includeOtherInUnionTypes` | | | ||
| `treatUnknownAsAny` | When `true`, unknown types at runtime are generated into TypeScript using the `any` type. | | ||
| `noSerdeLayer` | Allows you to control whether (de-)serialization code is generated. When true, the client uses JSON.parse() and JSON.stringify() instead. <br /> By default, the generated client includes a layer for serializing requests and deserializing responses. This has three benefits: <br /> 1. The client validates requests and response at runtime, client-side. <br /> 2. The client can support complex types, like Date and Set. <br /> 3. The generated types can stray from the wire/JSON representation to be more idiomatic. For example, when `noSerdeLayer` is disabled, all properties are camelCase, even if the server is expecting snake_case. | | ||
| `skipRequestValidation` | | | ||
| `skipResponseValidation` | By default, this config is set to `false` and the client will throw an error if the response from the server doesn't match the expected type (based on how the response is modeled in the API definition). Set this config to `true` to never throw an error if the response is misshapen. Rather, the client will log the issue using console.warn and return the data (cast to the expected response type). | | ||
| `outputEsm` | Allows you to control whether the generated TypeScript targets `CommonJS` or `esnext`. By default, the generated TypeScript targets `CommonJS`. | | ||
| `outputSourceFiles` | When `false` (default), the generator outputs .js and d.ts files. When `true`, the generator outputs raw TypeScript files. | | ||
| `retainOriginalCasing` | | | ||
| `allowExtraFields` | | | ||
|
||
<Note>The configuration options are accessible in [`ExpressCustomConfig.ts`](https://github.com/fern-api/fern/blob/main/generators/typescript/express/cli/src/custom-config/ExpressCustomConfig.ts).</Note> | ||
|
||
### Example Configuration | ||
|
||
<CodeBlock title="generators.yml"> | ||
```diff | ||
groups: | ||
express-server: | ||
generators: | ||
- name: fernapi/fern-typescript-express | ||
version: 0.15.0 | ||
output: | ||
location: local-file-system | ||
path: ../app/server | ||
+ config: | ||
+ useBrandedStringAliases: true | ||
+ noSerdeLayer: true | ||
``` | ||
</CodeBlock> |
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,133 @@ | ||
--- | ||
title: FastAPI Server | ||
description: Generate FastAPI server code from an API specification including OpenAPI, Swagger, AsyncAPI, and Fern Definition. | ||
subtite: Generate types and networking logic for your Python FastAPI server. | ||
slug: fastapi | ||
--- | ||
|
||
FastAPI is a modern, fast web framework for building APIs with Python based on standard Python type hints. It is a popular choice for building APIs and web servers. | ||
|
||
Fern outputs types and networking logic for your FastAPI server. This saves you time and adds compile-time safety by guaranteeing that you are serving the exact API that you specified in your API definition. | ||
|
||
## What Fern generates | ||
|
||
- Pydantic models for your API types | ||
- Exceptions that you can throw for non-200 responses | ||
- Abstract classes for you to define your business logic | ||
- All the networking/HTTP logic to call your API | ||
|
||
## Use the starter repository | ||
|
||
Clone the [starter repo](https://github.com/fern-api/fastapi-starter/) for FastAPI + React. | ||
|
||
## Demo video | ||
|
||
Learn how Fern can be helpful when building a FastAPI server. | ||
|
||
<div style="position: relative; padding-bottom: 62.5%; height: 0;"><iframe src="https://www.loom.com/embed/42de542022de4e55a1349383c7a465eb?sid=be3234f7-e0e2-4454-a510-caf4450b271d" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe></div> | ||
|
||
## Getting started | ||
|
||
<Steps> | ||
|
||
### Define your API | ||
|
||
Define your API using the [OpenAPI Specification](/learn/api-definition/openapi/overview) or the [Fern Definition](/learn/api-definition/fern/overview). | ||
|
||
### Add the FastAPI generator | ||
|
||
Add the FastAPI server generator to your `generators.yml` file. | ||
|
||
<CodeBlock title="generators.yml"> | ||
```yaml | ||
groups: | ||
fastapi-server: | ||
generators: | ||
- name: fernapi/fern-fastapi-server | ||
version: 0.9.3 | ||
output: | ||
location: local-file-system | ||
path: ../app/server | ||
``` | ||
</CodeBlock> | ||
|
||
### Generate code | ||
|
||
Run the [CLI](/learn/cli-api/cli-reference/cli-overview) command `fern generate --group fastapi-server`. | ||
|
||
### Implement the functions | ||
|
||
Provide the business logic by implementing each function. For example, if we were implenting the IMDb API, we would implement the `get_movie` function. | ||
|
||
<CodeBlock title="src/movies_service.py"> | ||
```python | ||
from .generated.fern import AbstractMoviesService, Movie, MovieDoesNotExistError, MovieId | ||
|
||
class MoviesService(AbstractMoviesService): | ||
def get_movie(self, *, movie_id: str) -> Movie: | ||
if movie_id == "titanic": | ||
return Movie( | ||
id=MovieId.from_str("titantic"), | ||
title="Titanic", | ||
rating=9.8, | ||
) | ||
raise MovieDoesNotExistError(MovieId.from_str(movie_id)) | ||
``` | ||
</CodeBlock> | ||
|
||
### Run the server | ||
|
||
```bash | ||
poetry run start | ||
``` | ||
|
||
### Call the API 🚀 | ||
|
||
```bash | ||
$ curl --location --request GET --silent 'localhost:8080/movies/titanic' | jq . | ||
{ | ||
"id": "titantic", | ||
"title": "Titanic", | ||
"rating": 9.8 | ||
} | ||
|
||
$ curl --location --request GET --silent 'localhost:8080/movies/oceans-11' | jq . | ||
{ | ||
"error": "MovieDoesNotExistError", | ||
"errorInstanceId": "f6e1d69c-bf97-42d5-bc89-5e42773e3880", | ||
"content": "oceans-11" | ||
} | ||
``` | ||
|
||
</Steps> | ||
|
||
## Advanced Configurations | ||
|
||
Tailor the `config` of the FastAPI server generator to your needs. The default values for all options are `false`. | ||
|
||
| Configuration Option | Description | | ||
| -------------------- | ----------- | | ||
| `include_validators` | | | ||
| `skip_formatting` | | | ||
| `async_handlers` | | | ||
|
||
<Note>The configuration options are accessible in [`custom_config.py`](https://github.com/fern-api/fern/blob/main/generators/python/src/fern_python/generators/fastapi/custom_config.py).</Note> | ||
|
||
### Example Configuration | ||
|
||
<CodeBlock title="generators.yml"> | ||
```diff | ||
groups: | ||
fastapi-server: | ||
generators: | ||
- name: fernapi/fern-fastapi-server | ||
version: 0.9.3 | ||
output: | ||
location: local-file-system | ||
path: ../app/server | ||
+ config: | ||
+ include_validators: true | ||
+ skip_formatting: true | ||
+ async_handlers: true | ||
``` | ||
|
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,22 @@ | ||
--- | ||
title: What is Server Code Generation? | ||
description: Generate server boilerplate code from an API specification including OpenAPI, Swagger, AsyncAPI, and Fern Definition. | ||
subtite: Generate types and networking logic for your server framework of choice. | ||
slug: server-codegen | ||
--- | ||
|
||
Fern's server-side generators output boilerplate application code that includes models and networking logic. This is intended for API First developers, who write their API definition before building their app. Fern supports generating backend code from an OpenAPI specification or Fern Definition. | ||
|
||
## Supported server frameworks | ||
|
||
- Node.js [Express](/learn/express) | ||
- Python [FastAPI](/learn/fastapi) | ||
- Java [Spring Boot](/learn/spring) | ||
|
||
Want to request a new server framework? [Let us know](https://github.com/fern-api/fern/issues/new?assignees=&labels=&projects=&template=feature-request.md&title=%5BFeature%5D). | ||
|
||
## Why use Fern for server code generation? | ||
|
||
1. **Save time**: generate boilerplate code instead of writing it. | ||
1. **Compile-time safety**: get validation that your endpoints are being served correctly. | ||
1. **Develop API-first**: design your API contract before you start building your app. Pick the best server framework for the job. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I’m here 🫣 this file should prob have express examples not fastapi examples