npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

huelgo-monad

v1.0.16

Published

Functional Programming Tools in Typescript

Readme

Huelgo-Monad

Desc

  • No More Variables !!
  • No More Try-Catch !!
  • No More side effect !!

Install

npm i huelgo-monad

Array

  • 여러자료구조를 이용하여 FP를 구성합니다.

mergeFamily

/**
 * @desc 가족은 항상 붙어있어야 해 (이주영 55세)
 */
export function mergeFamily<A, B, C, D, E, F, G, H>(
  a: A[],
  b: B[],
  c?: C[],
  d?: D[],
  e?: E[],
  f?: F[],
  g?: G[],
  h?: H[]
): (A | B | C | D | E | F | G | H)[] {
  let list: (A | B | C | D | E | F | G | H)[] = []
  for (const v of [a, b, c, d, e, f, g, h]) {
    if (v) {
      list = [...list, ...v]
    }
  }

  return list
}

interface SpreadFnParms<T> {
  fn: (v: T) => boolean
  idx: number
}

spreadFamily

/**
 * @desc 가끔은 가족끼리 떨어져있을 시간도 필요하죠 (이동규 30세)
 */
export function spreadFamily<T>(lists: T[], ...spreadFns: SpreadFnParms<T>[]): T[][] {
  let list: T[][] = new Array(spreadFns.length).fill(undefined).map(() => [])

  for (const v of lists) {
    for (const { fn, idx } of spreadFns) {
      if (fn(v)) {
        list[idx].push(v)
      }
    }
  }

  return list
}

Pipe

  • 여러 연결작업 및 FP를 활용하여 Monad를 구성합니다.

go

/**
 * @desc 앞으로 당당히 걸어가자
 * @param {initParam} initParam 초기값
 * @param {...fns} ...fns 조건 함수 들
 */
export const go = <T>(initParam: T, ...fns): T => {
  for (const fn of fns) initParam = fn(initParam)
  return initParam
}

asyncGo

/**
 * @desc 힘들지만 앞으로 당당히 걸어가자
 * @param {initParams} initParams 초기값
 * @param {...fns} ...fns 조건 함수 들
 */
export const asyncGo = async <T>(initParams: T, ...promiseFns): Promise<GoReturnParmas<string, T>> => {
  try {
    for (const promiseFn of promiseFns) initParams = await promiseFn(initParams)
    return {
      isOk: true,
      value: initParams,
    }
  } catch (e) {
    return {
      isOk: false,
      value: e,
    }
  }
}

mixedGo

/**
 * @desc 복잡하지만 앞으로 당당히 걸어가자
 * @param {initParams} initParams 초기값
 * @param {...fns} ...fns 조건 함수 들
 */
export const mixedGo = async <T>(initParams: T, ...funcs): Promise<GoReturnParmas<string, T>> => {
  try {
    for (const func of funcs) {
      if (isPromise(func)) {
        initParams = await func(initParams)
        continue
      }

      initParams = func(initParams)
    }

    return {
      isOk: true,
      value: initParams,
    }
  } catch (e) {
    return {
      isOk: false,
      value: e,
    }
  }
}

conditionGo

/**
 * @desc 조건을 이겨내보자
 * @param {initParam} initParam 초깃값
 * @param {isCondition} isCondition 조건값
 * @param {conditions} conditions 조건함수들
 */
export function conditionGo<E, T>(initParam: T, isCondition: boolean, ...conditions: ConditionParmas<E, T>[]): GoReturnParmas<E, T> {
  for (const { func, error } of conditions) {
    if (isCondition !== func(initParam)) {
      return {
        isOk: false,
        error,
      }
    }
  }

  return {
    isOk: true,
  }
}

conditionMixedGo

/**
 * @desc 힘든조건도 이겨내보자
 * @param {initParams} initParams 초깃값
 * @param {isCondition} isCondition 조건값
 * @param {condition} condition 조건함수들
 */
export async function conditionMixedGo<E, T>(
  initParams: T,
  isCondition: boolean,
  ...condition: ConditionParmas<E, T>[]
): Promise<GoReturnParmas<E, T>> {
  try {
    for (const { func, error } of condition) {
      // promise
      if (isPromise(func)) {
        if (isCondition !== (await func(initParams))) {
          return {
            isOk: false,
            error,
          }
        }
      }

      if (isCondition !== func(initParams)) {
        return {
          isOk: false,
          error,
        }
      }
    }

    return {
      isOk: true,
    }
  } catch (e) {
    return {
      isOk: false,
      error: e,
    }
  }
}

Inspect

fallThrough

/**
 * @desc 모든 함수들의대해서 검증한 후 결과값을 리턴합니다.
 * @returns {failReasons} 실패 이유들
 * @returns {totalCount} 전체 시도 함수 개수
 * @returns {successCount} 성공 함수 개수
 * @returns {failCount} 실패 함수 개수
 */
export function fallThrough<A, E>(
  { value, failBox, isErrorCond }: fallThroughParams<A, E>,
  fn1?: (value: A) => E,
  fn2?: (value: A) => E,
  fn3?: (value: A) => E,
  fn4?: (value: A) => E,
  fn5?: (value: A) => E,
  fn6?: (value: A) => E,
  fn7?: (value: A) => E,
  fn8?: (value: A) => E
): { failReasons: E[]; totalCount: number; successCount: number; failCount: number } {
  let [totalCount, successCount, failCount] = [0, 0, 0]

  for (const fn of [fn1, fn2, fn3, fn4, fn5, fn6, fn7, fn8].filter((it) => it)) {
    ++totalCount
    const result = fn(value)

    if (isErrorCond(result)) {
      failCount++
      failBox.push(result)
      continue
    }

    successCount++
  }

  return {
    failReasons: failBox,
    failCount,
    successCount,
    totalCount,
  }
}

breakThrough

export function breakThrough<A, E>(
  { value, isErrorCond }: breakThroughParams<A, E>,
  fn1?: (value: A) => E,
  fn2?: (value: A) => E,
  fn3?: (value: A) => E,
  fn4?: (value: A) => E,
  fn5?: (value: A) => E,
  fn6?: (value: A) => E,
  fn7?: (value: A) => E,
  fn8?: (value: A) => E
): { failReason: E; totalCount: number; failIndex: number } {
  let [totalCount, failIndex] = [0, 0]
  const fns = [fn1, fn2, fn3, fn4, fn5, fn6, fn7, fn8].filter((it) => it)
  totalCount = fns.length

  for (const fn of fns) {
    failIndex++
    const result = fn(value)
    if (isErrorCond(result)) {
      return {
        failReason: result,
        totalCount,
        failIndex,
      }
    }
  }

  return {
    failReason: null,
    totalCount,
    failIndex: null,
  }
}

Flow

flow

export function flow<T, K>(p: T, ...fns: ((p: T) => any)[]): K {
  return fns.reduce((acc, fn) => fn(acc), p) as K
}

asyncFlow

  • Todo

mixedFlow

  • Todo

Visual

visualIF

/**
 * @desc 기존 if문의 대해서 가독성 높은 코드로 visualization한 함수입니다.
 * @params {isParallel} isParallel 다른 구문도 통과시킬건지 여부
 */
export function visualIF<T>(
  isParallel: boolean,
  v: T,
  a: conditionIfParams<T>,
  b?: conditionIfParams<T>,
  c?: conditionIfParams<T>,
  d?: conditionIfParams<T>,
  e?: conditionIfParams<T>,
  f?: conditionIfParams<T>,
  g?: conditionIfParams<T>
): { result: T; correct: boolean; correctCount: number } {
  let [correct, correctCount] = [false, 0]
  for (const { isProfit, executeFn } of [a, b, c, d, e, f, g].filter((it) => it)) {
    if (isProfit(v)) {
      correct = true
      correctCount++

      v = executeFn(v)

      if (!isParallel)
        return {
          result: v,
          correct,
          correctCount,
        }
    }
  }

  return {
    result: v,
    correct,
    correctCount,
  }
}

Type

  • FP를 사용할때 필요한 타입을 정의합니다.

Option

/**
 * @desc 성공이냐? 실패냐? 그것이 문제로다
 * @type {Some<T>} 성공
 * @type {None} 실패
 */
export type Option<T> = Some<T> | None

Try

/**
 * @desc 왜 실패했니? 중요한건 과정이야
 * @type {Pass<T>} 성공
 * @type {Fail<E>} 실패
 */
export type Try<E, T> = Pass<T> | Fail<E>