diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml deleted file mode 100644 index 11156843c36..00000000000 --- a/.github/workflows/action.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: Check Markdown links - -on: push - -# prettier-ignore -jobs: - markdown-link-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: gaurav-nelson/github-action-markdown-link-check@v1 diff --git a/docs/README.md b/docs/README.md index adfdcf31559..dda881d23f0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,6 +2,11 @@ > **Fern is a framework for building APIs.** You can think of it as an alternative to OpenAPI (f.k.a Swagger). + +

Fern TypeScript Server Tutorial

+ +
+ ## How does it work? ![Overview diagram](assets/diagrams/overview-diagram.png) @@ -30,12 +35,12 @@ With an API definition, development projects that involve multiple engineers/tea ## What is a Fern API Definition? -A [**Fern API Definition**](markdown_files/definition.md#what-is-a-fern-api-definition) is a set of YAML files that describe your API. +A [**Fern API Definition**](_/definition.md#what-is-a-fern-api-definition) is a set of YAML files that describe your API. ## What are Fern Generators? -[**Generators**](markdown_files/generators.md) convert a Fern API Definition into clients, servers, and documentation. +[**Generators**](_/generators.md) convert a Fern API Definition into clients, servers, and documentation. ## How is this different than OpenAPI? -Fern is optimized for [kick-ass codegen](markdown_files/faq.md#_1-how-is-fern-different-than-openapi-fka-swagger). +Fern is optimized for [kick-ass codegen](_/comparison.md#_1-how-is-fern-different-than-openapi-fka-swagger). diff --git a/docs/markdown_files/channels.md b/docs/_/channels.md similarity index 100% rename from docs/markdown_files/channels.md rename to docs/_/channels.md diff --git a/docs/markdown_files/cli.md b/docs/_/cli.md similarity index 100% rename from docs/markdown_files/cli.md rename to docs/_/cli.md diff --git a/docs/_/comparison.md b/docs/_/comparison.md new file mode 100644 index 00000000000..b4b4f6da233 --- /dev/null +++ b/docs/_/comparison.md @@ -0,0 +1,7 @@ +# How is Fern different than OpenAPI (f.k.a Swagger)? + +- **Higher-quality code generation**: Fern is more restrictive in what you can model, enabling idiomatic, easy-to-use code generation. + +- **Protocol agnostic**: Fern lets you define RESTful services alongside WebSocket subscriptions. + +- **Ease of use**: Fern runs code generators remotely and manages publishing packages to registries (e.g., NPM, Maven, PyPI). You get a dependency that you can start using right away. diff --git a/docs/markdown_files/definition.md b/docs/_/definition.md similarity index 100% rename from docs/markdown_files/definition.md rename to docs/_/definition.md diff --git a/docs/markdown_files/errors.md b/docs/_/errors.md similarity index 100% rename from docs/markdown_files/errors.md rename to docs/_/errors.md diff --git a/docs/markdown_files/fern-config-json.md b/docs/_/fern-config-json.md similarity index 100% rename from docs/markdown_files/fern-config-json.md rename to docs/_/fern-config-json.md diff --git a/docs/markdown_files/fernrc.md b/docs/_/fernrc.md similarity index 100% rename from docs/markdown_files/fernrc.md rename to docs/_/fernrc.md diff --git a/docs/markdown_files/generators.md b/docs/_/generators.md similarity index 81% rename from docs/markdown_files/generators.md rename to docs/_/generators.md index c24490b78db..e9286b362f4 100644 --- a/docs/markdown_files/generators.md +++ b/docs/_/generators.md @@ -13,3 +13,15 @@ | | | | OpenAPI | converts a Fern Definition to an [OpenAPI Spec](https://swagger.io/resources/open-api/) | fern add openapi | [fern-openapi](https://github.com/fern-api/fern-openapi) | | | | + +## How does remote code generation work? + +Code generators run remotely in the cloud. They take a set of Fern API Definition YAML files, run the generators listed in `.fernrc.yml, and produce generated files as an output. Files can output locally (i.e., seen in the file system of your IDE) or remotely (i.e., in a package manager like NPM, Maven, or PyPI). + +### Generating clients + +![client generators](../assets/diagrams/frontend-diagram.png) + +### Generating servers + +![server generators](../assets/diagrams/backend-diagram.png) diff --git a/docs/markdown_files/ids.md b/docs/_/ids.md similarity index 100% rename from docs/markdown_files/ids.md rename to docs/_/ids.md diff --git a/docs/markdown_files/imdb.md b/docs/_/imdb.md similarity index 63% rename from docs/markdown_files/imdb.md rename to docs/_/imdb.md index 5b199de824e..6440fe0e572 100644 --- a/docs/markdown_files/imdb.md +++ b/docs/_/imdb.md @@ -1,9 +1,14 @@ -# Tutorial: IMDb +# TypeScript Server Tutorial: IMDb This guide uses an example API for IMDb (the International Movie Database) that introduces you to using Fern. We'll generate a TypeScript server and a Postman Collection to implement and test our API. + +

Video walkthrough

+ +
+ ## Step 0: Prerequisites - Install [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) @@ -32,6 +37,10 @@ In the root of your backend repo, run: fern init ``` +When it asks you for your `organization`, just write `imdb`. + +In the `.fernrc.yml`, let's change the name of our api from `api` to `imdb-api`. +
What happens: @@ -62,7 +71,7 @@ fern add typescript
What happens: -`.fernrc.yml` will now list two generators: +`.fernrc.yml` will now list a generator: ```diff name: api @@ -80,13 +89,18 @@ fern add typescript ## Step 4: Run the generator +```bash +fern generate +``` + In the terminal, you'll see `Published @imdb-fern/imdb-api-server@x.x.x` which we'll add as a dependency. By default, Fern publishes dependencies to a private registry. ```bash # Teach npm about the Fern private registry npm config set --location project @imdb-fern:registry https://npm-dev.buildwithfern.com/ -npm install @imdb-fern/api-server@x.x.x +# Your version may be different, but this version will also work +npm install @imdb-fern/imdb-api-server@0.0.19 ``` ## Step 5: Implement the server @@ -95,15 +109,27 @@ We'll create a new file `server.ts` at the root of our project. This will be a s ```ts // server.ts -import { GetMovieErrorBody, MovieId } from "@imdb-fern/api-server/model"; -import { MoviesService } from "@imdb-fern/api-server/services"; +import { GetMovieErrorBody, MovieId } from "@imdb-fern/imdb-api-server/model"; +import { MoviesService } from "@imdb-fern/imdb-api-server/services"; import express from "express"; const app = express(); app.use( MoviesService.expressMiddleware({ - // TODO + createMovie: () => { + return { + ok: true, + body: MovieId.of("iron-man-3"), + }; + }, + + getMovie: () => { + return { + ok: false, + error: GetMovieErrorBody.NotFoundError(), + }; + }, }) ); @@ -111,38 +137,6 @@ console.log("Listening for requests..."); app.listen(8080); ``` -Our IDE will give us red lines indicating that we need to add missing properties. - -![server.ts error message](../assets/tutorial/server.ts%20error%20message.png) - -You can implement the missing methods, for example: - -```diff - // server.ts - import express from "express"; - const app = express(); - - app.use(MoviesService.expressMiddleware({ -+ createMovie: (request) => { -+ console.log(request); -+ return { -+ ok: true, -+ body: MovieId.of("iron-man-3") -+ } -+ }, - -+ getMovie: () => { -+ return { -+ ok: false, -+ error: GetMovieErrorBody.NotFoundError() -+ } -+ } - })) - - console.log("Listening for requests..."); - app.listen(8080); -``` - ## Step 6: Run the server ```bash @@ -151,23 +145,29 @@ npx ts-node server.ts In the terminal, you should see `Listening for requests...` -## Step 6: Add the Postman generator +## Step 7: Add the Postman generator + +In another terminal, let's run: ```bash fern add postman fern generate ``` -In the `api/` folder you'll see `collection.json` that we'll import to Postman. +In the `api/` folder you'll see `generated-postman.json` that we'll import to Postman. + +## Step 8: Hit the server from Postman + +Open Postman and File -> Import `api/generated-postman.json`. -## Step 7: Hit the server from Postman +Select the `createMovie` endpoint and hit `Send`. You should get **`iron-man-3`** back from your server. -Open Postman and File -> Import `api/generated-postman/collection.json`. +![createMovie-postman](../assets/tutorial/createMovie-postman.png) -Select the `createMovie` endpoint and hit `Send`. You should get a response back from your server **`iron-man-3`**. +Select the `getMovie` endpoint and hit `Send`. As expected, we get a 404 response back. -![postman-testing](../assets/tutorial/postman-testing.png) +![getMovie-postman](../assets/tutorial/getMovie-postman.png) -## Step 8: Celebrate +## Step 9: Celebrate 🎉 You've successfully implemented a simple IMDb server using Fern. You're invited to join our [Discord](https://discord.gg/JkkXumPzcG). diff --git a/docs/markdown_files/imports.md b/docs/_/imports.md similarity index 100% rename from docs/markdown_files/imports.md rename to docs/_/imports.md diff --git a/docs/markdown_files/services.md b/docs/_/services.md similarity index 100% rename from docs/markdown_files/services.md rename to docs/_/services.md diff --git a/docs/markdown_files/types.md b/docs/_/types.md similarity index 100% rename from docs/markdown_files/types.md rename to docs/_/types.md diff --git a/docs/_sidebar.md b/docs/_sidebar.md index b624804d5de..26be369ee4b 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -2,15 +2,15 @@ - Getting started - - [Tutorial: IMDb](markdown_files/imdb.md) - - [CLI](markdown_files/cli.md) + - [Tutorial: IMDb](_/imdb.md) + - [CLI](_/cli.md) - Concepts - - [Fern API Definition](markdown_files/definition.md) - - [Generators](markdown_files/generators.md) + - [Fern API Definition](_/definition.md) + - [Generators](_/generators.md) - Reference p - - [FAQs](markdown_files/faq.md) + - [Comparison with OpenAPI](_/comparison.md) - [Join the Discord](https://discord.gg/JkkXumPzcG) diff --git a/docs/assets/tutorial/createMovie-postman.png b/docs/assets/tutorial/createMovie-postman.png new file mode 100644 index 00000000000..d970f5b961c Binary files /dev/null and b/docs/assets/tutorial/createMovie-postman.png differ diff --git a/docs/assets/tutorial/getMovie-postman.png b/docs/assets/tutorial/getMovie-postman.png new file mode 100644 index 00000000000..5f862eaffcc Binary files /dev/null and b/docs/assets/tutorial/getMovie-postman.png differ diff --git a/docs/assets/tutorial/postman-testing.png b/docs/assets/tutorial/postman-testing.png deleted file mode 100644 index 8ed43f3fe4d..00000000000 Binary files a/docs/assets/tutorial/postman-testing.png and /dev/null differ diff --git a/docs/assets/tutorial/server.ts error message.png b/docs/assets/tutorial/server.ts error message.png deleted file mode 100644 index 2c2b36770fd..00000000000 Binary files a/docs/assets/tutorial/server.ts error message.png and /dev/null differ diff --git a/docs/markdown_files/faq.md b/docs/markdown_files/faq.md deleted file mode 100644 index 016dfc79b98..00000000000 --- a/docs/markdown_files/faq.md +++ /dev/null @@ -1,21 +0,0 @@ -# Frequently Asked Questions - -## 1. How is Fern different than OpenAPI (f.k.a Swagger)? - -- **Higher-quality code generation**: Fern is more restrictive in what you can model, enabling idiomatic, easy-to-use code generation. - -- **Protocol agnostic**: Fern lets you define RESTful services alongside WebSocket subscriptions. - -- **Ease of use**: Fern runs code generators remotely and manages publishing packages to registries (e.g., NPM, Maven, PyPI). You get a dependency that you can start using right away. - -## 2. How does remote code generation work? - -Code generators run remotely in the cloud. They take a set of Fern API Definition YAML files, run the generators listed in `.fernrc.yml, and produce generated files as an output. Files can output locally (i.e., seen in the file system of your IDE) or remotely (i.e., in a package manager like NPM, Maven, or PyPI). - -### Generating clients - -![client generators](../assets/diagrams/frontend-diagram.png) - -### Generating servers - -![server generators](../assets/diagrams/backend-diagram.png)