next-cookie-crud

A simple util to perform CRUD operations on cookies in Next.js environment.

next-cookie-crud
import { isSSR } from 'util';
import cookie from 'cookie';
import { IncomingHttpHeaders } from 'http';
import Cookie from 'js-cookie';

const setCookie = (
  name: string,
  data: unknown,
  options: Cookie.CookieAttributes = {}
) => {
  Cookie.set(name, typeof data === 'string' ? data : JSON.stringify(data), {
    expires: 10000,
    ...options
  });
};

const removeCookie = (name: string) => {
  Cookie.remove(name);
};

const parseCookies = (
  headers?: IncomingHttpHeaders
): {
  [key: string]: string;
} => cookie.parse(headers ? headers.cookie || '' : document.cookie);

const parseCookie = <T>(
  name: string,
  headers?: IncomingHttpHeaders
): T | undefined => {
  const val = parseCookies(headers)[name];
  try {
    return JSON.parse(val);
  } catch (error) {
    return val as unknown as T;
  }
};

interface ICookieValues {
  user_info: null | string;
}

interface ICookieUtil {
  get: <T extends keyof ICookieValues>(
    name: T,
    headers?: IncomingHttpHeaders
  ) => ICookieValues[T];
  set: <T extends keyof ICookieValues>(
    name: T,
    value: Exclude<ICookieValues[T], null>,
    options?: Cookie.CookieAttributes
  ) => void;
  delete: <T extends keyof ICookieValues>(name: T) => void;
}

// These values are to be used only on client side
const COOKIE_VALUES: ICookieValues = {
  user_info: null // user info
};

const getCookieValue = <T extends keyof ICookieValues>(
  name: T,
  headers?: IncomingHttpHeaders
): ICookieValues[T] | null => {
  if (isSSR()) {
    if (!headers) return null;
    return parseCookie(name, headers) || null;
  }

  return (
    ((COOKIE_VALUES[name] || parseCookie(name)) as ICookieValues[T]) || null
  );
};

const cookieUtil: ICookieUtil = {
  set: (name, value, options) => {
    setCookie(name, value, options);
    if (!isSSR()) {
      COOKIE_VALUES[name] = value;
    }
  },
  get: (name, headers) => getCookieValue(name, headers),
  delete: (name) => {
    removeCookie(name);
    COOKIE_VALUES[name] = null;
  }
};

const setVarsFromCookies = (headers?: IncomingHttpHeaders): void => {
  const cookies = parseCookies(headers);

  Object.keys(COOKIE_VALUES).forEach((property) => {
    const cookieVal = cookies[property];

    let data;
    try {
      data = JSON.parse(cookieVal);
    } catch (error) {
      data = cookieVal;
    }

    COOKIE_VALUES[property as keyof ICookieValues] = data || null;
  });
};

/**
 * Cookies to be deleted on logout
 */
const deleteCookiesForLogout = (): void => {};

export { parseCookies, cookieUtil, setVarsFromCookies, deleteCookiesForLogout };