Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More agnostic API #298

Closed
5 tasks done
StefanoMagrassi opened this issue Feb 6, 2020 · 0 comments · Fixed by #299
Closed
5 tasks done

More agnostic API #298

StefanoMagrassi opened this issue Feb 6, 2020 · 0 comments · Fixed by #299

Comments

@StefanoMagrassi
Copy link
Contributor

StefanoMagrassi commented Feb 6, 2020

It's time to make appy more Contactlab-agnostic...

This will impact the API and how to extend the base functionalities in order to respond to different needs.

Main purposes are:

  • removing io-ts as dependency;
  • removing the request / api dichotomy in favour of an unified API;
  • being as close as possible to fetch's objects like Headers, Request or Response in order to make integration easier;
  • implementation of a simple core API that can be extended by users based on their needs;
  • providing some useful base combinators for common use-cases.

Work in progress in the v3 branch

API

The base API should be like this

// ReaderTaskEither for better composability
interface Req<A> extends RTE.ReaderTaskEither<ReqInput, Err, Resp<A>> {}

// Maps fetch()'s parameters
type ReqInput = RequestInfo | RequestInfoInit;
type RequestInfoInit = [RequestInfo, RequestInit];

// A response carries the actual data (already retrieved) and the original Response
interface Resp<A> {
  response: Response;
  data: A;
}

// Just two kind of errors
type Err = RequestError | ResponseError;

// Request error carries the original input of Req
interface RequestError {
  type: 'RequestError';
  error: Error;
  input: RequestInfoInit;
}

// Response error carries the original Response
interface ResponseError {
  type: 'ResponseError';
  response: Response;
  error: Error;
}

Combinators

In order to make extending the library functionalities easier, any other feature should then be expressed as simple combinator Req<A> -> Req<A>.

So, for example, decoding the response body as JSON:

type Decoder<A> = (u: unknown) => Either<Error, A>;

declare function withDecoder<A, B>(decoder: Decoder<B>): (ra: Req<A>) => Req<B>;

or adding headers to the request:

// `HeadersInit` is the type of the `headers` key in the fetch()'s `init` parameter
// see https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters

declare function withHeaders<A>(hs: HeadersInit): (req: Req<A>) => Req<A>;

or setting request's body (for POSTs or PUTs):

// `body` can be a plain object/JSON

declare function withBody<A>(body: unknown): (req: Req<A>) => Req<A>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant