{"id":24286005,"url":"https://github.com/extra-memoize/extra-memoize","last_synced_at":"2026-04-13T03:01:48.716Z","repository":{"id":40510300,"uuid":"368386197","full_name":"extra-memoize/extra-memoize","owner":"extra-memoize","description":"🌳 Yet another memoize library.","archived":false,"fork":false,"pushed_at":"2026-02-14T14:57:28.000Z","size":4737,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-14T21:44:14.472Z","etag":null,"topics":["browser","esm","library","nodejs","npm-package","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/extra-memoize","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/extra-memoize.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-05-18T03:10:25.000Z","updated_at":"2026-02-14T14:57:32.000Z","dependencies_parsed_at":"2025-08-14T17:23:19.030Z","dependency_job_id":null,"html_url":"https://github.com/extra-memoize/extra-memoize","commit_stats":{"total_commits":103,"total_committers":2,"mean_commits":51.5,"dds":0.08737864077669899,"last_synced_commit":"1e20e6114950fad0c0b510dea1641e3ea9a0ba5f"},"previous_names":["blackglory/extra-memoize"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/extra-memoize/extra-memoize","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extra-memoize%2Fextra-memoize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extra-memoize%2Fextra-memoize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extra-memoize%2Fextra-memoize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extra-memoize%2Fextra-memoize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/extra-memoize","download_url":"https://codeload.github.com/extra-memoize/extra-memoize/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extra-memoize%2Fextra-memoize/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31737849,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-12T22:19:12.206Z","status":"online","status_checked_at":"2026-04-13T02:00:06.623Z","response_time":93,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","esm","library","nodejs","npm-package","typescript"],"created_at":"2025-01-16T07:19:44.244Z","updated_at":"2026-04-13T03:01:48.710Z","avatar_url":"https://github.com/extra-memoize.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# extra-memoize\nYet another memoize library.\n\n## Philosophy\nMost memoize functions include strategies (such as TTL), which will actually cause poor cache performance, because memoize functions can only use common interfaces to implement related strategies.\n\n`extra-memoize` takes another approach, its memoize function is very light. It delegates the implementation of the strategies to the cache layer and cache wrapper. This allows the cache backend to fully utilize their performance.\n\n## Install\n```sh\nnpm install --save extra-memoize\n# or\nyarn add extra-memoize\n```\n\n## Usage\n```ts\nimport { memoize } from 'extra-memoize'\nimport { LRUCache } from '@extra-memoize/memory-cache'\n\nconst cache = new LRUCache(100)\nconst memoized = memoize({ cache }, fn)\n```\n\n## API\n```ts\nenum State {\n  Miss = 'miss'\n, Hit = 'hit'\n, Reuse = 'reuse'\n, StaleWhileRevalidate = 'stale-while-revalidate'\n, StaleIfError = 'stale-if-error'\n}\n\ninterface ICache\u003cT\u003e {\n  set(key: string, value: T): void\n  get(key: string): [State.Miss]\n                  | [State.Hit, T]\n}\n\ninterface IAsyncCache\u003cT\u003e {\n  set(key: string, value: T): Promise\u003cvoid\u003e\n  get(key: string): Promise\u003c\n                    | [State.Miss]\n                    | [State.Hit, T]\n                    \u003e\n}\n\ninterface IStaleWhileRevalidateCache\u003cT\u003e {\n  set(key: string, value: T): void\n  get(key: string): [State.Miss]\n                  | [\n                    | State.Hit\n                    | State.StaleWhileRevalidate\n                    , T\n                    ]\n}\n\ninterface IStaleWhileRevalidateAsyncCache\u003cT\u003e {\n  set(key: string, value: T): Promise\u003cvoid\u003e\n  get(key: string): Promise\u003c\n                    | [State.Miss]\n                    | [\n                      | State.Hit\n                      | State.StaleWhileRevalidate\n                      , T\n                      ]\n                    \u003e\n}\n\ninterface IStaleIfErrorCache\u003cT\u003e {\n  set(key: string, value: T): void\n  get(key: string): [State.Miss]\n                  | [\n                    | State.Hit\n                    | State.StaleIfError\n                    , T\n                    ]\n}\n\ninterface IStaleIfErrorAsyncCache\u003cT\u003e {\n  set(key: string, value: T): Promise\u003cvoid\u003e\n  get(key: string): Promise\u003c\n                    | [State.Miss]\n                    | [\n                      | State.Hit\n                      | State.StaleIfError\n                      , T\n                      ]\n                    \u003e\n}\n\ninterface IStaleWhileRevalidateAndStaleIfErrorCache\u003cT\u003e {\n  set(key: string, value: T): void\n  get(key: string): [State.Miss]\n                  | [\n                    | State.Hit\n                    | State.StaleWhileRevalidate\n                    | State.StaleIfError\n                    , T\n                    ]\n}\n\ninterface IStaleWhileRevalidateAndStaleIfErrorAsyncCache\u003cT\u003e {\n  set(key: string, value: T): Promise\u003cvoid\u003e\n  get(key: string): Promise\u003c\n                    | [State.Miss]\n                    | [\n                      | State.Hit\n                      | State.StaleWhileRevalidate\n                      | State.StaleIfError\n                      , T\n                      ]\n                    \u003e\n}\n```\n\n### memoize\n```ts\ntype VerboseResult\u003cT\u003e = [T, State.Hit | State.Miss]\n\ninterface IMemoizeOptions\u003cCacheValue, Args extends any[]\u003e {\n  cache: ICache\u003cCacheValue\u003e\n  name?: string\n  verbose?: boolean = false\n\n  createKey?: (args: Args, name?: string) =\u003e string\n\n  /**\n   * Used to judge whether a function execution is too slow.\n   * Only when the excution time of function is\n   * greater than or equal to the value (in milliseconds),\n   * the return value of the function will be cached.\n   */\n  executionTimeThreshold?: number = 0\n}\n\nfunction memoize\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: IMemoizeOptions\u003cCacheValue, Args\u003e \u0026 { verbose: true }\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e VerboseResult\u003cResult\u003e\nfunction memoize\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: IMemoizeOptions\u003cCacheValue, Args\u003e \u0026 { verbose: false }\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e Result\nfunction memoize\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: Omit\u003cIMemoizeOptions\u003cCacheValue, Args\u003e, 'verbose'\u003e\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e Result\nfunction memoize\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: IMemoizeOptions\u003cCacheValue, Args\u003e\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e Result | VerboseResult\u003cResult\u003e\n```\n\n### memoizeAsync\n```ts\ntype VerboseResult\u003cT\u003e = [T, State.Hit | State.Miss | State.Reuse]\n\ninterface IMemoizeAsyncOptions\u003cCacheValue, Args extends any[]\u003e {\n  cache: ICache\u003cCacheValue\u003e | IAsyncCache\u003cCacheValue\u003e\n  name?: string\n  verbose?: boolean = false\n\n  // The default is extra-json-stable-stringify([args, name])\n  createKey?: (args: Args, name?: string) =\u003e string\n\n  /**\n   * Used to judge whether a function execution is too slow.\n   * Only when the excution time of function is\n   * greater than or equal to the value (in milliseconds),\n   * the return value of the function will be cached.\n   */\n  executionTimeThreshold?: number\n}\n\nfunction memoizeAsync\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: IMemoizeAsyncOptions\u003cCacheValue, Args\u003e \u0026 { verbose: true }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cVerboseResult\u003cResult\u003e\u003e\nfunction memoizeAsync\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: IMemoizeAsyncOptions\u003cCacheValue, Args\u003e \u0026 { verbose: false }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeAsync\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: Omit\u003cIMemoizeAsyncOptions\u003cCacheValue, Args\u003e, 'verbose'\u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeAsync\u003cCacheValue, Result extends CacheValue, Args extends any[]\u003e(\n  options: IMemoizeAsyncOptions\u003cCacheValue, Args\u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult | VerboseResult\u003cResult\u003e\u003e\n```\n\n### memoizeStaleWhileRevalidate\n```ts\ntype VerboseResult\u003cT\u003e = [\n  T\n, State.Hit | State.Miss | State.Reuse | State.StaleWhileRevalidate\n]\n\ninterface IMemoizeStalwWhileRevalidateOptions\u003c\n  CacheValue\n, Args extends any[]\n\u003e {\n  cache:\n  | IStaleWhileRevalidateCache\u003cCacheValue\u003e\n  | IStaleWhileRevalidateAsyncCache\u003cCacheValue\u003e\n  name?: string\n  verbose?: boolean = false\n\n  // The default is extra-json-stable-stringify([args, name])\n  createKey?: (args: Args, name?: string) =\u003e string\n\n  /**\n   * Used to judge whether a function execution is too slow.\n   * Only when the excution time of function is\n   * greater than or equal to the value (in milliseconds),\n   * the return value of the function will be cached.\n   */\n  executionTimeThreshold?: number\n}\n\nfunction memoizeStaleWhileRevalidate\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStalwWhileRevalidateOptions\u003cCacheValue, Args\u003e \u0026 { verbose: true }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cVerboseResult\u003cResult\u003e\u003e\nfunction memoizeStaleWhileRevalidate\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStalwWhileRevalidateOptions\u003cCacheValue, Args\u003e \u0026 { verbose: false }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeStaleWhileRevalidate\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: Omit\u003cIMemoizeStalwWhileRevalidateOptions\u003cCacheValue, Args\u003e, 'verbose'\u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeStaleWhileRevalidate\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStalwWhileRevalidateOptions\u003cCacheValue, Args\u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult | VerboseResult\u003cResult\u003e\u003e\n```\n\n### memoizeStaleIfError\n```ts\ntype VerboseResult\u003cT\u003e = [T, State.Hit | State.Miss | State.StaleIfError]\n\ninterface IMemoizeStaleIfErrorOptions\u003cCacheValue, Args extends any[]\u003e {\n  cache: IStaleIfErrorCache\u003cCacheValue\u003e\n  name?: string\n  verbose?: boolean = false\n\n  // The default is extra-json-stable-stringify([args, name])\n  createKey?: (args: Args, name?: string) =\u003e string\n\n  /**\n   * Used to judge whether a function execution is too slow.\n   * Only when the excution time of function is\n   * greater than or equal to the value (in milliseconds),\n   * the return value of the function will be cached.\n   */\n  executionTimeThreshold?: number\n}\n\nfunction memoizeStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStaleIfErrorOptions\u003cCacheValue, Args\u003e \u0026 { verbose: true }\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e VerboseResult\u003cResult\u003e\nfunction memoizeStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStaleIfErrorOptions\u003cCacheValue, Args\u003e \u0026 { verbose: false }\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e Result\nfunction memoizeStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: Omit\u003cIMemoizeStaleIfErrorOptions\u003cCacheValue, Args\u003e, 'verbose'\u003e\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e Result\nfunction memoizeStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStaleIfErrorOptions\u003cCacheValue, Args\u003e\n, fn: (...args: Args) =\u003e Result\n): (...args: Args) =\u003e Result | VerboseResult\u003cResult\u003e\n```\n\n### memoizeAsyncStaleIfError\n```ts\ntype VerboseResult\u003cT\u003e = [\n  T\n, | State.Hit\n  | State.Miss\n  | State.Reuse\n  | State.StaleIfError\n]\n\ninterface IMemoizeStaleIfErrorOptions\u003cCacheValue, Args extends any[]\u003e {\n  cache: IStaleIfErrorCache\u003cCacheValue\u003e | IStaleifErrorAsyncCache\u003cCacheValue\u003e\n  name?: string\n  verbose?: boolean = false\n\n  // The default is extra-json-stable-stringify([args, name])\n  createKey?: (args: Args, name?: string) =\u003e string\n\n  /**\n   * Used to judge whether a function execution is too slow.\n   * Only when the excution time of function is\n   * greater than or equal to the value (in milliseconds),\n   * the return value of the function will be cached.\n   */\n  executionTimeThreshold?: number\n}\n\nfunction memoizeAsyncStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeAsyncStaleIfError\u003cCacheValue, Args\u003e \u0026 { verbose: true }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cVerboseResult\u003cResult\u003e\u003e\nfunction memoizeAsyncStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeAsyncStaleIfError\u003cCacheValue, Args\u003e \u0026 { verbose: false }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeAsyncStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: Omit\u003cIMemoizeAsyncStaleIfError\u003cCacheValue, Args\u003e, 'verbose'\u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeAsyncStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeAsyncStaleIfError\u003cCacheValue, Args\u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult | VerboseResult\u003cResult\u003e\u003e\n```\n\n### memoizeStaleWhileRevalidateAndStaleIfError\n```ts\ntype VerboseResult\u003cT\u003e = [\n  T\n, | State.Hit\n  | State.Miss\n  | State.Reuse\n  | State.StaleWhileRevalidate\n  | State.StaleIfError\n]\n\ninterface IMemoizeStaleWhileRevalidateAndStaleIfError\u003c\n  CacheValue\n, Args extends any[]\n\u003e {\n  cache:\n  | IStaleWhileRevalidateAndStaleIfErrorCache\u003cCacheValue\u003e\n  | IStaleWhileRevalidateAndStaleIfErrorAsyncCache\u003cCacheValue\u003e\n  name?: string\n  verbose?: boolean = false\n\n  // The default is extra-json-stable-stringify([args, name])\n  createKey?: (args: Args, name?: string) =\u003e string\n\n  /**\n   * Used to judge whether a function execution is too slow.\n   * Only when the excution time of function is\n   * greater than or equal to the value (in milliseconds),\n   * the return value of the function will be cached.\n   */\n  executionTimeThreshold?: number\n}\n\nfunction memoizeStaleWhileRevalidateAndStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStaleWhileRevalidateAndStaleIfError\u003cCacheValue, Args\u003e\n         \u0026 { verbose: true }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cVerboseResult\u003cResult\u003e\u003e\nfunction memoizeStaleWhileRevalidateAndStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStaleWhileRevalidateAndStaleIfError\u003cCacheValue, Args\u003e\n         \u0026 { verbose: false }\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeStaleWhileRevalidateAndStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: Omit\u003c\n    IMemoizeStaleWhileRevalidateAndStaleIfError\u003cCacheValue, Args\u003e\n  , 'verbose'\n  \u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult\u003e\nfunction memoizeStaleWhileRevalidateAndStaleIfError\u003c\n  CacheValue\n, Result extends CacheValue\n, Args extends any[]\n\u003e(\n  options: IMemoizeStaleWhileRevalidateAndStaleIfError\u003cCacheValue, Args\u003e\n, fn: (...args: Args) =\u003e Awaitable\u003cResult\u003e\n): (...args: Args) =\u003e Promise\u003cResult | VerboseResult\u003cResult\u003e\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextra-memoize%2Fextra-memoize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fextra-memoize%2Fextra-memoize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextra-memoize%2Fextra-memoize/lists"}