Skip to content

Commit e4bf405

Browse files
committed
docs(rest): data validation
1 parent f500885 commit e4bf405

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

src/content/006-getting-started-with-rest.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ tags: ['Getting Started', 'rest', 'rest-service', 'rest-client-fetch', 'rest-cli
66
image: img/006-getting-started-with-rest-cover.jpg
77
date: '2021-06-23T12:58:20.257Z'
88
draft: false
9-
excerpt: Designing and implementing APIs can be hard and consuming them can be frustrating, if they doesn't work as expected. REST API as a Typescript interface for the rescue!
9+
excerpt: Designing and implementing APIs can be hard and consuming them can be frustrating, if they doesn't work as expected. REST API as a Typescript interface to the rescue!
1010
---
1111

1212
### The problem 🤷‍♂️
@@ -176,6 +176,6 @@ So, step by step:
176176
### The main gotcha: Let's break all the thingzzz!!!!4!!!💥
177177

178178
There's an ancient refactoring technique in the _type-safe dreamlands_: If you can change your type definitions and try to recompile, you will see immediately where it will break your code.
179-
The good news: Now you can do that with your API definition - your service and your frontend will be still type-protected 🙌
179+
We have good news: **Now you can do that with your API definition** - your backend service and your frontend app will is type-protected now 🙌
180180

181-
![Does clients depends on APIs?](img/006-hulk.gif)
181+
![hulk breaks thingz](img/006-hulk.gif)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
layout: post
3+
title: Data validation with REST and json-schemas
4+
author: [gallayl]
5+
tags: ['Getting Started', 'rest', 'rest-service', 'rest-client-fetch', 'rest-client-got', 'json-schemas']
6+
image: img/007-data-validation-cover.jpg
7+
date: '2021-06-23T13:58:20.257Z'
8+
draft: false
9+
excerpt: We have a strongly typed REST API interface with build-time type checking. Can we build runtime validation with a minimal effort? (Spoiler alert - yesss)
10+
---
11+
12+
### Prerequisites
13+
14+
Read the [previous article](/006-getting-started-with-rest) about type-safe REST APIs, if you haven't yet. It will give a huge boost on productivity. Seriously... go go go...
15+
So, glad you've back. Now let's get down to business...
16+
17+
### Some sad facts about Typescript interfaces - and a possible solution
18+
19+
Let's face it - you have a well-defined REST API in a Typescript interface but you cannot use Typescript interfaces realtime as they _does not exists realtime_ 😿
20+
But there's a solution that can be easily adopted - JSON Schemas
21+
22+
![the relatime interface usage](img/007-impossible.jpg)
23+
24+
So the plan is:
25+
1. Design the API
26+
1. Create a JSON Schema from the API definitions
27+
1. Wire some validation logic on the Backend
28+
29+
### Generating the Schema
30+
FuryStack offers some help when it comes to defining / designing the API interface - as mentioned in the last article. There is a nice tool that will help us create the JSON Schema - [ts-json-schema-generator](https://github.com/vega/ts-json-schema-generator)
31+
So if we have an interface ready, we can generate the JSON schema with a simple command from an NPM script:
32+
```sh
33+
yarn ts-json-schema-generator -f tsconfig.json --no-type-check -p common/src/path/to/my/api.schema.ts -o common/src/path/to/my/api.schema.json
34+
```
35+
36+
Once it is done, you can access / re-export it in your `common` package - maybe you have to enable `resolveJsonModule` in your tsconfig.
37+
38+
```ts
39+
import * as mySchema from './path/to/my/api.schema.json'
40+
export { mySchema }
41+
```
42+
43+
44+
### Validation in the Service
45+
46+
Once you will be able to import your schema, you can simply use the `Validate()` method in REST Api. Let's take for example the endpoint from the previous post.
47+
48+
```ts
49+
import { mySchema } from 'common'
50+
import { Validate } from '@fuystack/rest-service'
51+
52+
const customHeadersEndpoint: RequestAction<CustomHeaders> = Validate({
53+
schema: mySchema
54+
schemaName: 'CustomHeaders'
55+
})(async ({ headers }) => {
56+
console.log(headers)
57+
return JsonResult(headers)
58+
})
59+
```
60+
61+
### The Gotchas
62+
63+
- All input data (query, headers, url, body) will be validated - **in depth**
64+
- You can define nested types, string literals, optional parameters, type intersections, nearly everything that Typescript can offer. You can throw errors on additional parameters as well.
65+
- You will automatically get nice 400 responses with detailed error messages if you miss something
66+
- Schema can be re-generated as your API changes
95.6 KB
Loading

src/content/img/007-impossible.jpg

73.5 KB
Loading

0 commit comments

Comments
 (0)