open-index/open-npm huggingface dataset:
npm package: @pagopa/handler-kit
Description: A minimal toolkit to make `handlers` in TypeScript & `fp-ts`
Latest version: 1.1.1

# @pagopa/handler-kit

A minimal toolkit to make `handlers` in TypeScript & `fp-ts`

## What is an Handler?

An `Handler` is a specialization of fp-ts' `ReaderTaskEither` that takes a value as `input` and ensures uniform error handling and validation.

It is particularly useful for creating HTTP-agnostic "controllers" that can be adapted to any framework.

This package contains useful functions for creating handlers, manipulating them, abstracting HTTP controllers, and uniformly handling errors

## How to use it

```typescript
import * as H from "@pagopa/handler-kit";
import * as L from "@pagopa/logger";

import * as E from "fp-ts/Either";
import * as RTE from "fp-ts/ReaderTaskEither";
import * as TE from "fp-ts/TaskEither";
import { pipe, flow } from "fp-ts/function";
import { lookup } from "fp-ts/Record";

import * as t from "io-ts";

const GetMoviesBody = t.type({
  genre: t.keyof({
    action: null,
    comedy: null,
    drama: null,
    horror: null,
    "sci-fi": null,
  }),
});

type GetMoviesBody = t.TypeOf<typeof GetMoviesBody>;

const movies = {
  action: ["die hard"],
  horror: ["shining", "the exorcist"],
};

const getMoviesByGenre =
  (genre: GetMoviesBody["genre"]) =>
  (r: { movies: Record<string, string[]> }) =>
    pipe(
      r.movies,
      lookup(genre),
      TE.fromOption(
        () => new H.HttpNotFoundError("there are no movies for this genre")
      )
    );

// Reads genre from HTTP body,
// then performs an effecful search
// and returns an HTTP response.
const GetMovies = H.of((req: H.HttpRequest) =>
  pipe(
    req.body,
    // perform a refinement with io-ts, and returns a ValidationError
    // that represents a 422 HTTP response
    H.parse(GetMoviesBody),
    E.map(({ genre }) => genre),
    RTE.fromEither,
    RTE.chainW(getMoviesByGenre),
    RTE.map((movies) => ({ items: movies })),
    // wrap in a 200 HTTP response, with content-type JSON
    RTE.map(H.successJson),
    // converts Error instances to problem json (RFC 7807) objects
    RTE.orElseW(flow(H.toProblemJson, H.problemJson, RTE.of))
  )
);

// Run the handler
// too boilerplate? :P don't panic, see the handler-kit adapters

const httpRequest = {
  method: "POST",
  body: {
    genre: "sci-fi",
  },
  url: "https://my-req.url/",
  query: {},
  headers: {},
  path: {},
};

GetMovies({
  input: httpRequest,
  inputDecoder: H.HttpRequest,
  logger: {
    log: (r) => () => console.log(r),
    format: L.format.simple,
  },
  movies,
})();
```

See the unit tests for other examples
npm package: @pagopa/handler-kit-azure-func
Description: `@pagopa/handler-kit` adapter for `Azure Functions`
Latest version: 2.0.8

# @pagopa/handler-kit-azure-func

`@pagopa/handler-kit` adapter for `Azure Functions`

### How to use it

```typescript
import { httpAzureFunction } from "@pagopa/handler-kit-azure-func";

// Given an Handler
// (from the @pagopa/handler README example)

const GetMovies = H.of((req: H.HttpRequest) =>
  pipe(
    req.body,
    // perform a refinement with io-ts, and returns a ValidationError
    // that represents a 422 HTTP response
    H.parse(GetMoviesBody),
    E.map(({ genre }) => genre),
    RTE.fromEither,
    RTE.chainW(getMoviesByGenre),
    RTE.map((movies) => ({ items: movies })),
    // wrap in a 200 HTTP response, with content-type JSON
    RTE.map(H.successJson),
    // converts Error instances to problem json (RFC 7807) objects
    RTE.orElseW(flow(H.toProblemJson, H.problemJson, RTE.of))
  )
);

// instead of wiring manually the dependencies

/*
GetMovies({
  input: ...,
  inputDecoder: ...,
  logger: ...,
  movies: ...
})*/

// just use "httpAzureFunction"

const GetMoviesFunction = httpAzureFunction(GetMovies)({
  movies,
});

// now GetMoviesFunction can be called by the Azure runtime
```

See the unit tests for other examples
npm package: @pagopa/handler-kit-express
Description: `@pagopa/handler-kit-express` adapter for `Express`
Latest version: 2.0.0

# @pagopa/handler-kit-express

`@pagopa/handler-kit-express` adapter for `Express`

### How to use it

```typescript
import { expressHandler } from "@pagopa/handler-kit-express";

// Given an Handler
// (from the @pagopa/handler README example)

const GetMovies = H.of((req: H.HttpRequest) =>
  pipe(
    req.body,
    // perform a refinement with io-ts, and returns a ValidationError
    // that represents a 422 HTTP response
    H.parse(GetMoviesBody),
    E.map(({ genre }) => genre),
    RTE.fromEither,
    RTE.chainTaskEither(getMoviesByGenre),
    RTE.map((movies) => ({ items: movies })),
    // wrap in a 200 HTTP response, with content-type JSON
    RTE.map(H.successJson),
    // convert Error instances to problem json (RFC 7808) objects
    RTE.orElseW(flow(H.toProblemJson, H.problemJson))
  )
);

// instead of wiring manually the dependencies

/*
GetMovies({
  input: ...,
  inputDecoder: ...,
  logger: ...,
  movies: ...
})*/

// just use "expressHandler"
const GetMoviesExpress = expressHandler(GetMovies)({
  movies,
});

const ConsoleLogger: L.Logger = {
  log: (r) => () => console.log(r),
  format: L.format.json,
};

// now GetMoviesRoute can be called by the Express runtime
const app = express.default();
app.use(express.json());

// decorate "req" with "log" function
app.use(logger(ConsoleLogger));

// enable HTTP request logging
app.use(access());

app.post("/", GetMoviesExpress);

app.listen(3001, () => {
  // eslint-disable-next-line no-console
  console.log("Server ready on port 3001");
});
```

See the unit tests for other examples