{"version":3,"file":"index.js","names":[],"sources":["../index.ts"],"sourcesContent":["//\n// Main\n//\n\ntype Func = (...args: any[]) => any\n\nexport interface Cache<K, V> {\n  create: CacheCreateFunc<K, V>\n}\n\ninterface CacheCreateFunc<K, V> {\n  (): DefaultCache<K, V>\n}\n\ninterface DefaultCache<K, V> {\n  get(key: K): V | undefined\n  set(key: K, value: V | undefined): void\n}\n\nexport type Serializer = (args: any[]) => string\n\nexport interface Options<F extends Func> {\n  cache?: Cache<string, ReturnType<F>>\n  serializer?: Serializer\n  strategy?: MemoizeFunc<F>\n}\n\nexport interface ResolvedOptions<F extends Func> {\n  cache: Cache<string, ReturnType<F>>\n  serializer: Serializer\n}\n\nexport interface MemoizeFunc<F extends Func> {\n  (fn: F, options?: Options<F>): F\n}\n\nexport function memoize<F extends Func>(fn: F, options?: Options<F>): F {\n  const cache = options && options.cache ? options.cache : cacheDefault\n\n  const serializer =\n    options && options.serializer ? options.serializer : serializerDefault\n\n  const strategy =\n    options && options.strategy ? options.strategy : strategyDefault\n\n  return strategy(fn, {\n    cache,\n    serializer,\n  })\n}\n\n//\n// Strategy\n//\n\nfunction isPrimitive(value: any): boolean {\n  return (\n    value == null || typeof value === 'number' || typeof value === 'boolean'\n  ) // || typeof value === \"string\" 'unsafe' primitive for our needs\n}\n\nexport type StrategyFn = <F extends Func>(\n  this: unknown,\n  fn: F,\n  cache: DefaultCache<string, ReturnType<F>>,\n  serializer: Serializer,\n  arg: any\n) => any\n\nfunction monadic<F extends Func>(\n  this: unknown,\n  fn: F,\n  cache: DefaultCache<string, ReturnType<F>>,\n  serializer: Serializer,\n  arg: any\n) {\n  const cacheKey = isPrimitive(arg) ? arg : serializer(arg)\n\n  let computedValue = cache.get(cacheKey)\n  if (typeof computedValue === 'undefined') {\n    computedValue = fn.call(this, arg)\n    cache.set(cacheKey, computedValue)\n  }\n\n  return computedValue\n}\n\nfunction variadic<F extends Func>(\n  this: unknown,\n  fn: F,\n  cache: DefaultCache<string, ReturnType<F>>,\n  serializer: Serializer\n) {\n  const args = Array.prototype.slice.call(arguments, 3)\n  const cacheKey = serializer(args)\n\n  let computedValue = cache.get(cacheKey)\n  if (typeof computedValue === 'undefined') {\n    computedValue = fn.apply(this, args)\n    cache.set(cacheKey, computedValue)\n  }\n\n  return computedValue\n}\n\nfunction assemble<F extends Func>(\n  fn: F,\n  context: unknown,\n  strategy: StrategyFn,\n  cache: DefaultCache<string, ReturnType<F>>,\n  serialize: Serializer\n): F {\n  return strategy.bind(context, fn, cache, serialize) as F\n}\n\nfunction strategyDefault<F extends Func>(\n  this: unknown,\n  fn: F,\n  options: ResolvedOptions<F>\n) {\n  const strategy = fn.length === 1 ? monadic : variadic\n\n  return assemble(\n    fn,\n    this,\n    strategy,\n    options.cache.create(),\n    options.serializer\n  )\n}\n\nfunction strategyVariadic<F extends Func>(\n  this: unknown,\n  fn: F,\n  options: ResolvedOptions<F>\n) {\n  return assemble(\n    fn,\n    this,\n    variadic,\n    options.cache.create(),\n    options.serializer\n  )\n}\n\nfunction strategyMonadic<F extends Func>(\n  this: unknown,\n  fn: F,\n  options: ResolvedOptions<F>\n) {\n  return assemble(fn, this, monadic, options.cache.create(), options.serializer)\n}\n\n//\n// Serializer\n//\n\nconst serializerDefault: Serializer = function (): string {\n  return JSON.stringify(arguments)\n}\n\n//\n// Cache\n//\n\nclass ObjectWithoutPrototypeCache {\n  private cache: Record<string, any>\n\n  constructor() {\n    this.cache = Object.create(null) as Record<string, any>\n  }\n\n  get(key: string) {\n    return this.cache[key]\n  }\n\n  set<T>(key: string, value: T): void {\n    this.cache[key] = value\n  }\n}\n\nconst cacheDefault: Cache<any, any> = {\n  create: function create() {\n    return new ObjectWithoutPrototypeCache()\n  },\n}\n\n//\n// API\n//\n\nexport interface Strategies<F extends Func> {\n  variadic: MemoizeFunc<F>\n  monadic: MemoizeFunc<F>\n}\n\nexport const strategies: Strategies<Func> = {\n  variadic: strategyVariadic as MemoizeFunc<Func>,\n  monadic: strategyMonadic as MemoizeFunc<Func>,\n}\n"],"mappings":";AAoCA,SAAgB,QAAwB,IAAO,SAAyB;CACtE,MAAM,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,QAAQ;CAEzD,MAAM,aACJ,WAAW,QAAQ,aAAa,QAAQ,aAAa;CAKvD,QAFE,WAAW,QAAQ,WAAW,QAAQ,WAAW,gBAAA,CAEnC,IAAI;EAClB;EACA;CACF,CAAC;AACH;AAMA,SAAS,YAAY,OAAqB;CACxC,OACE,SAAS,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU;AAEnE;AAUA,SAAS,QAEP,IACA,OACA,YACA,KACA;CACA,MAAM,WAAW,YAAY,GAAG,IAAI,MAAM,WAAW,GAAG;CAExD,IAAI,gBAAgB,MAAM,IAAI,QAAQ;CACtC,IAAI,OAAO,kBAAkB,aAAa;EACxC,gBAAgB,GAAG,KAAK,MAAM,GAAG;EACjC,MAAM,IAAI,UAAU,aAAa;CACnC;CAEA,OAAO;AACT;AAEA,SAAS,SAEP,IACA,OACA,YACA;CACA,MAAM,OAAO,MAAM,UAAU,MAAM,KAAK,WAAW,CAAC;CACpD,MAAM,WAAW,WAAW,IAAI;CAEhC,IAAI,gBAAgB,MAAM,IAAI,QAAQ;CACtC,IAAI,OAAO,kBAAkB,aAAa;EACxC,gBAAgB,GAAG,MAAM,MAAM,IAAI;EACnC,MAAM,IAAI,UAAU,aAAa;CACnC;CAEA,OAAO;AACT;AAEA,SAAS,SACP,IACA,SACA,UACA,OACA,WACG;CACH,OAAO,SAAS,KAAK,SAAS,IAAI,OAAO,SAAS;AACpD;AAEA,SAAS,gBAEP,IACA,SACA;CACA,MAAM,WAAW,GAAG,WAAW,IAAI,UAAU;CAE7C,OAAO,SACL,IACA,MACA,UACA,QAAQ,MAAM,OAAO,GACrB,QAAQ,UACV;AACF;AAEA,SAAS,iBAEP,IACA,SACA;CACA,OAAO,SACL,IACA,MACA,UACA,QAAQ,MAAM,OAAO,GACrB,QAAQ,UACV;AACF;AAEA,SAAS,gBAEP,IACA,SACA;CACA,OAAO,SAAS,IAAI,MAAM,SAAS,QAAQ,MAAM,OAAO,GAAG,QAAQ,UAAU;AAC/E;AAMA,MAAM,oBAAgC,WAAoB;CACxD,OAAO,KAAK,UAAU,SAAS;AACjC;AAMA,IAAM,8BAAN,MAAkC;CAGhC,cAAc;EACZ,KAAK,QAAQ,OAAO,OAAO,IAAI;CACjC;CAEA,IAAI,KAAa;EACf,OAAO,KAAK,MAAM;CACpB;CAEA,IAAO,KAAa,OAAgB;EAClC,KAAK,MAAM,OAAO;CACpB;AACF;AAEA,MAAM,eAAgC,EACpC,QAAQ,SAAS,SAAS;CACxB,OAAO,IAAI,4BAA4B;AACzC,EACF;AAWA,MAAa,aAA+B;CAC1C,UAAU;CACV,SAAS;AACX"}