diff --git a/website/docs/how-to-guides/_category_.json b/website/docs/how-to-guides/_category_.json index 69dca425..4525a16f 100644 --- a/website/docs/how-to-guides/_category_.json +++ b/website/docs/how-to-guides/_category_.json @@ -1,7 +1,8 @@ { - "label": "How-To Guide", + "label": "How-To Guides", "position": 3, "link": { - "type": "generated-index" + "type": "generated-index", + "description": "5 minutes to practice the most important api-ts concepts." } } diff --git a/website/docs/how-to-guides/parsing.json-strings.md b/website/docs/how-to-guides/parsing.json-strings.md new file mode 100644 index 00000000..9fdac5a2 --- /dev/null +++ b/website/docs/how-to-guides/parsing.json-strings.md @@ -0,0 +1,102 @@ +# Decoding JSON from Headers, Query Parameters, and URL Parameters + +Though we know headers, url parameters, and query parameters will be received as a +`string` or `string[]` value, due to a limitation in api-ts, `httpRequest` only accepts +codecs that decode values starting from the `unknown` type. Consequently, decoding a +header, url parameter, or query parameter with a codec like `JsonFromString`, which can +only decode values typed as `string`, will produce a error like: + +``` +Type 'Type' is not assignable to type 'Mixed'. + Types of property 'validate' are incompatible. + Type 'Validate' is not assignable to type 'Validate'. + Type 'unknown' is not assignable to type 'string'. +``` + +There's a straightforward pattern you can use when you have a value typed as `unknown` +but need to decode it with a codec that can only decode a narrower type. This pattern is +called codec chaining: + +```typescript +declare const JsonFromString: t.Type; +declare const t.string: t.Type; + +const myCodec: t.Type = t.string.pipe(JsonFromString); +``` + +Here, `t.string` decodes a value from `unknown` to `string`, and then `JsonFromString` +decodes the same value from `string` to `Json`. + +For example: + +```typescript +import * as t from 'io-ts'; +import { nonEmptyArray, JsonFromString, NumberFromString } from 'io-ts-types'; +import { httpRequest, optional } from '@api-ts/io-ts-http'; + +// Define the Filter type for the JSON string +const Filter = t.type({ + category: t.string, + tags: t.array(t.string), + price: t.type({ + min: t.number, + max: t.number, + }), +}); + +// Define the SearchRequest codec +const SearchRequest = httpRequest({ + params: { + userId: NumberFromString, + }, + query: { + q: t.string, + filter: t.string.pipe(JsonFromString).pipe(Filter), + tags: nonEmptyArray(t.string), + sort: optional(t.string), + }, + headers: { + authorization: t.string, + }, +}); + +// Example request object +const example = { + params: { + userId: '84938492', + }, + query: { + q: 'test', + filter: + '{"category":"books","tags":["crypto","trading"],"price":{"min":10,"max":50}}', + tags: ['tag1', 'tag2', 'tag3'], + sort: 'price', + }, + headers: { + authorization: 'Bearer token', + }, +}; + +// Decode the example +const decoded = SearchRequest.decode(example); +if (decoded._tag === 'Right') { + console.log(decoded); + /* + Expected decoded output + { + userId: 84938492, + q: 'test', + filter: { + category: 'books', + tags: ['crypto', 'trading'], + price: { min: 10, max: 50 }, + }, + tags: ['tag1', 'tag2', 'tag3'], + sort: 'price', + authorization: 'Bearer token', + }; + */ +} else { + console.error('Decoding failed:', decoded.left); +} +``` diff --git a/website/docs/intro.md b/website/docs/intro.md index 8d78bd44..a0ae6213 100644 --- a/website/docs/intro.md +++ b/website/docs/intro.md @@ -2,11 +2,16 @@ sidebar_position: 1 --- -### Lorem ipsum +# Introduction -```python hello.py -# mark[16:24] -print("This is Code Hike") -``` +`io-ts-http` brings type safety to HTTP data handling in TypeScript by embracing the +"[parse, don't validate]" philosophy. Rather than simply checking if incoming HTTP data +is valid, it also parses raw, less-structured data (like strings or JSON) into strongly +typed, precise objects using the `io-ts` library. This parsing happens at the system +boundary, ensuring all types have use cases in your code. Once parsed, you can trust the +data satisfies both [type and semantic analysis]. -Lorem ipsum dolor sit amet. +[parse, don't validate]: + https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/ +[type and semantic analysis]: + https://bitgo.github.io/api-ts/docs/tutorial-basics/create-an-api-spec/#what-problem-does-io-ts-http-solve