Skip to content

Commit

Permalink
Ds/concepts docs (#162)
Browse files Browse the repository at this point in the history
* Add readme draft

* Capitalize ID

* Update example and lowercase websocket

* Updating readme spec

* Add concepts folder

* Removing files

* Update readme and add concept draft

* Revise core concepts

* Revise readme from food deliver example to weather report

* Update readme

* Undo readme changes

* Fix casing I hope

* revise docs

* Remove hathora.yml

Co-authored-by: Danny Sheridan <[email protected]>
Co-authored-by: Danny Sheridan <[email protected]>
  • Loading branch information
3 people authored May 17, 2022
1 parent 3900702 commit b78355c
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 80 deletions.
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License
# MIT License

Copyright (c) 2022 Birch
Copyright (c) 2022 Birch Solutions, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
166 changes: 91 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,110 @@
# Fern

Fern is an open source framework that makes it easier to build APIs.
</p>

Fern allows you to
TODO Fern makes it easy to define APIs.

1. Define a source-of-truth for your API
2. Autogenerate idiomatic & typesafe clients and servers
3. Supports WebSocket and REST APIs
4. Easily manage backwards compatiblity
### Single source of truth

Fern is interoperable with Open API so you are never locked in.
Define your data model and your APIs in **one place** in your repo.

## Example Spec
### Type-safe servers and clients

Below we have written out a sample spec for a Food Delivery App.
Run `fern generate` to automatically generate **server stubs** and **type-safe clients**.

> "Wow, this codegen is so idiomatic!" - Chuck Norris
## What languages are supported?

The Fern compiler reads API definitions written in the [human-readable YML format](/docs/fern_definitions.md) and produces a JSON [intermediate representation](/docs/intermediate_representation.md) (IR).

| **Language** | **Server Stub** | **Client** |
| ------------ | ---------------- | ---------- |
| Java |||
| TypeScript | 🚧 _in progress_ ||
| Python | 🚧 | 🚧 |

_Interested in another language? [Get in touch]([email protected])_

## Let's do an example

Here's a simple API to get the current weather report:

```yaml
ids:
- MenuItemId
- OrderId: long
# api.yml

types:
DeliveryMethod:
enum:
- PICKUP
- DELIVERY
OrderStatus:
union:
pickup: PickupOrderStatus
delivery: DeliveryOrderStatus
PickupOrderStatus:
WeatherReport:
properties:
tempInFahrenheit: double
humidity:
type: integer
docs: a number between 0 and 100
conditions: WeatherConditions
WeatherConditions:
enum:
- PREPARING
- READY_FOR_PICKUP
- PICKED_UP
DeliveryOrderStatus:
enum:
- PREPARING
- ON_THE_WAY
- DELIVERED
- SUNNY
- CLOUDY
- RAINY

services:
http:
OrderService:
base-path: /order
WeatherService:
base-path: /weather
endpoints:
addItemToCart:
docs: Adds a menu item to a cart.
method: POST
path: /add
request:
properties:
menuItemId: MenuItemId
quantity: integer
placeOrder:
method: POST
path: /order/new
request:
properties:
deliveryMethod: DeliveryMethod
tip: optional<double>
response: OrderId
errors:
union:
emptyCart: EmptyCartError

websocket:
OrderStatusChannel:
messages:
subscribeToOrderStatus:
origin: client
body: OrderId
response:
properties:
orderStatus: OrderStatus
etaInMinutes: integer
behavior: ongoing
errors:
union:
notFound: OrderNotFoundError

errors:
OrderNotFoundError:
http:
statusCode: 404
EmptyCartError:
http:
statusCode: 400
getWeather:
method: GET
path: /{zipCode}
parameters:
zipCode: string
response: WeatherReport
```
### The server
Here's the Typescript/express server stubs that Fern generates:
TODO
### The client
Let's say we published the client to npm... TODO make this better. Here's an example of someone consuming it:
```ts
import { WeatherService } from "weather-api";

const weatherService = WeatherService.create({
baseUrl:
})

const weatherReport = await Weather

```

The app has REST endpoints so that clients can add items to their cart and place orders. It also has a websocket channel where a client can subscribe to updates about an order's ETA.
## Contributing

The team welcomes contributions! To make code changes to one of the Fern repos:

- Fork the repo and make a branch
- Write your code
- Open a PR (optionally linking to a Github issue)

## Getting started

### Installation

`$ npm install -g fern-api`

### Initialize Fern in your repo

`fern init`

### Generate code

`fern generate`

`fern add`

## License

This spec can be used to generate clients and servers.
This tooling is made available under the [MIT License](LICENSE).
173 changes: 173 additions & 0 deletions docs/concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Model

</p>

The _Fern model_ describes the data model used to defining your APIs in Fern.

## Core Concepts

- [imports](#imports)
- [ids](#ids)
- [types](#types)
- [errors](#errors)
- [services](#services)

### Imports

_Reference Core Concepts from other Fern models._

```yml
import:
blog: blog.yml
user: user.yml
```
### Ids
_Identifiers are named and default to string._
```yml
ids:
blog: BlogPostId
user: UserId
publication: PublicationId
```
### Types
_Users may define the following kinds of types. These can be referenced by their name elsewhere in a Fern data model._
- [Primitives](#primitives)
- [Objects](#objects)
- [Aliases](#aliases)
- [Enums](#enums)
- [Containers](#containers)
### Errors
_Users may define a name and structure for errors so that clients can expect specific pieces of information on failure._
_Structured errors_ have the following properties:
- _Name_ - a user chosen description e.g. `BlogNotFoundError`
- _Status code_ - an optional HTTP status code e.g. `404`

```yml
errors:
BlogNotFoundError:
http:
statusCode: 404
UserInvalidError:
http:
statusCode: 400
```

### Services

_HTTP endpoints that support `GET`, `PUT`, `POST`, `DELETE`_

```yml
services:
http:
PostsService:
base-path: /posts
endpoints:
getPost:
method: GET
path: /{postId}
parameters:
postId: string
request: CreatePostRequest
response: PostId
publishPost:
method: POST
path: /publish
request: PublishPostRequest
response: PublishPostResponse
deletePost:
method: DELETE
path: /{postId}
parameters:
postId: string
```

### Primitives

_Types that are built-in to the Fern data model._

```yml
types:
Primitives:
properties:
a: any # a catch-all type
b: boolean
c: double
d: integer
e: long
f: string
```

### Objects

_A collection of named properties, each of which has their own Fern type. Below is an example of a `Post` object._

```yml
types:
Post:
docs: A blog post
properties:
id: PostId
type: PostType
title: string
author: Author
content: string
Podcast:
docs: An audio version of a blog post
extends: Post
properties:
duration: integer
coverArt: string
```

### Aliases

_A new name for an existing type to make a user's types more self-documenting._

```yml
types:
PostType:
properties:
length: PostLength
```

### Unions

_A tagged union data structure that can take on several different, but fixed, types._

```yml
types:
Author:
union:
anonymous: {}
name: string
```

### Enums

_A type consisting of named string variants._

```yml
types:
BlogStatus:
enum:
- DRAFT
- PUBLISHED
- ARCHIVED
```

### Containers

- `list<T>` - an ordered sequence of items of type `T`.
- `map<K, V>` - values of type `V` each indexed by a unique key of type `K` (keys are unordered).
- `optional<T>` - represents a value of type `T` which is either present or not present.
- `set<T>` - a collection of distinct values of type `T`.
Loading

0 comments on commit b78355c

Please sign in to comment.