teamdigitale/italia-app

View on GitHub
ts/store/transforms/dateISO8601Tranform.ts

Summary

Maintainability
A
2 hrs
Test Coverage
import * as O from "fp-ts/lib/Option";
import * as E from "fp-ts/lib/Either";
import { createTransform, TransformIn, TransformOut } from "redux-persist";
import { pipe } from "fp-ts/lib/function";
import { DateFromISOString } from "../../utils/dates";

/**
 * dateFieldsTransformable contains the name of the fields that are
 * instance of Date and those ones we want to persist/rehydrate in redux persist store
 *
 * actually entities state (whitelisted in this transform) contains these following date (Timestamp) fields
 *
 * EntitiesState
 *  - MessageState
 *    - CreatedMessageWithContent
 *      - created_at *
 *      - content
 *        - due_date *
 *    - CreatedMessageWithoutContent
 *      - created_at *
 *
 * https://www.pivotaltracker.com/story/show/167507349
 */
const dateFieldsTransformable = new Set<string>([
  "created_at",
  "due_date",
  "nextLegalAttempt",
  "lastUsage"
]);

/**
 *  if value is a Date object, a string in ISO8601 format is returned
 */

const dataReplacer = (_: any, value: any): any => {
  if (value !== undefined && value instanceof Date) {
    return value.toISOString();
  }
  return value;
};

/**
 *  if value is in a string in ISO8601 format the corrisponding Date object is returned
 */
const dateReviver = (key: any, value: any): any => {
  const decodedValue = DateFromISOString.decode(value);
  return dateFieldsTransformable.has(key) && E.isRight(decodedValue)
    ? decodedValue.right
    : value;
};

const encoder: TransformIn<any, string> = (value: any, _: string): any =>
  pipe(
    value,
    O.fromNullable,
    O.map(v => JSON.parse(JSON.stringify(v), dataReplacer)),
    O.toUndefined
  );

const decoder: TransformOut<string, any> = (value: any, _: string): any =>
  pipe(
    value,
    O.fromNullable,
    O.map(v => JSON.parse(JSON.stringify(v), dateReviver)),
    O.toUndefined
  );

/**
 * date tasformer will be applied only to entities (whitelist)
 */
export const DateISO8601Transform = createTransform(encoder, decoder, {
  whitelist: ["entities", "fail", "walletById"]
});