Skip to content

Instantly share code, notes, and snippets.

@zaetrik
zaetrik / example-failed-request.ts
Created April 19, 2020 10:43
Functional JS API Requests - Failed Request
getExchangeRatesForCountry(CountryCode.GGG).then(console.log);
// => It returns our failed request
// The error is wrapped inside of a TaskEither monad
{
_tag: 'Left',
left: Error: Request failed with status code 400
at createError (/Users/code/javascript/functional-js/node_modules/axios/lib/core/createError.js:16:15)
at settle (/Users/code/javascript/functional-js/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/Users/code/javascript/functional-js/node_modules/axios/lib/adapters/http.js:236:11)
@zaetrik
zaetrik / example-succesful-request.ts
Created April 19, 2020 10:45
Functional JS API Requests - Successful Request
getExchangeRatesForCountry(CountryCode.USD).then(console.log);
// => It returns our validated response
// wrapped inside of a TaskEither monad
{
_tag: 'Right',
right: {
rates: {
CAD: 1.4069981584,
HKD: 7.7505524862,
@zaetrik
zaetrik / get-exchange-rates.ts
Created April 19, 2020 10:45
Functional JS API Requests -Get Exchange Rates
const getExchangeRatesForCountry = (countryCode: CountryCode) =>
pipe(
// tryCatch transforms our Promise that may reject to a Promise that never rejects and returns an Either instead
taskEither.tryCatch(
// We need an anonymous function here because we can only use tryCatch with functions that return Lazy<Promise<any>>
() => fetchExchangeRatesForCountry(countryCode),
either.toError
),
taskEither.chain(
// flow => function composition (from left to right)
@zaetrik
zaetrik / simple-api-request.ts
Created April 19, 2020 10:46
Functional JS API Requests - Making a Simple API Request
const fetchExchangeRatesForCountry = async (
cc: CountryCode
): Promise<ExchangeRates> => {
const res = await axios.get(
`https://api.exchangeratesapi.io/latest?base=${cc}`
);
return res.data as ExchangeRates;
};
@zaetrik
zaetrik / validate-api-response.ts
Created April 19, 2020 10:47
Functional JS API Requests - Validating the API Response
const validateExchangeRates = (countryCode: CountryCode) => (
response: ExchangeRates
): either.Either<Error, ExchangeRates> => {
return response.base === countryCode
? either.right(response as ExchangeRates)
: either.left(
Error(
`Invalid exchange rates data! Expected ${countryCode} but got ${response.base}`
)
);
@zaetrik
zaetrik / complete-example.ts
Created April 19, 2020 10:50
Functional JS API Requests - Complete Example
import { either, taskEither } from "fp-ts";
import { flow } from "fp-ts/lib/function";
import { pipe } from "fp-ts/lib/pipeable";
import axios from "axios";
/**
* In this real life example we fetch data from an API and validate the result with the usage of Either and TaskEither
*/
enum CountryCode {
@zaetrik
zaetrik / api-request-with-validation.ts
Last active April 19, 2020 14:38
Functional JS API Requests - API Request with Validation
const APIRequestWithValidation = (validator) => (...requestArgs) =>
pipe(
taskEither.tryCatch(() => makeApiRequest(...requestArgs), either.toError),
taskEither.chain(flow(validator, taskEither.fromEither))
)();
@zaetrik
zaetrik / omicron-middleware-req-to-option.ts
Last active April 30, 2020 07:45
Omicron - Middleware: req to Option
import * as E from "fp-ts/lib/Either";
import * as O from "fp-ts/lib/Option";
import { RouteHandler, r, useMiddleware, Middleware, HttpRequest } from "@zaetrik/omicron";
const toOption: Middleware = (req: HttpRequest): E.Either<Error, O.Option<RequestBody>> =>
E.tryCatch(() =>
O.some(req.body), E.toError);
const routeHandler: RouteHandler = r
("/")
@zaetrik
zaetrik / omicron-middleware-validate-request.ts
Last active April 29, 2020 12:43
Omicron - Middleware: Validate request
import * as t from "io-ts";
import * as E from "fp-ts/lib/Either";
import { pipe } from "fp-ts/lib/pipeable";
import {
RouteHandler,
r,
useMiddleware,
Middleware,
HttpRequest
} from "@zaetrik/omicron";
@zaetrik
zaetrik / omicron-start-server.ts
Last active April 29, 2020 11:47
Omicron: Start a server
import * as omicron from "@zaetrik/omicron";
import { IO } from "fp-ts/lib/IO";
const indexHandler = omicron.r
("/") // Path
("GET") // HTTP method
((req) => "Hello 👋") // The handler function
((req, error) => `Oops! An error occured ⚠️ => ${error.message}`); // The error handler function
const listener = omicron.httpListener({