Comparing version 1.0.0 to 1.1.0
@@ -1,1 +0,1 @@ | ||
var createLRU=k=>{var{max:v,onEviction:t}=k;if(!(Number.isInteger(v)&&v>0))throw new TypeError("`max` must be a positive integer");var u=0,y=0,d=0,h=[],m=new Map,l=new Array(v).fill(void 0),f=new Array(v).fill(void 0),b=new Array(v).fill(0),i=new Array(v).fill(0),o=(e,r)=>{if(e!==d){var n=b[e],s=i[e];e===y?y=n:(r==="get"||s!==0)&&(b[s]=n),n!==0&&(i[n]=s),b[d]=e,i[e]=d,b[e]=0,d=e}},A=()=>{var e=y,r=l[e];return t==null||t(r,f[e]),m.delete(r),l[e]=void 0,f[e]=void 0,y=b[e],y!==0&&(i[y]=0),u--,u===0&&(y=d=0),h.push(e),e};return{set(e,r){if(e!==void 0){var n=m.get(e);n===void 0?(n=u===v?A():h.length>0?h.pop():u,m.set(e,n),l[n]=e,u++):t==null||t(e,f[n]),f[n]=r,u===1?y=d=n:o(n,"set")}},get(e){var r=m.get(e);if(r!==void 0)return r!==d&&o(r,"get"),f[r]},peek:e=>{var r=m.get(e);return r!==void 0?f[r]:void 0},has:e=>m.has(e),*keys(){for(var e=d,r=0;r<u;r++)yield l[e],e=i[e]},*values(){for(var e=d,r=0;r<u;r++)yield f[e],e=i[e]},*entries(){for(var e=d,r=0;r<u;r++)yield[l[e],f[e]],e=i[e]},forEach:e=>{for(var r=d,n=0;n<u;n++){var s=l[r],g=f[r];e(g,s),r=i[r]}},delete(e){var r=m.get(e);if(r===void 0)return!1;t==null||t(e,f[r]),m.delete(e),h.push(r),l[r]=void 0,f[r]=void 0;var n=i[r],s=b[r];return n!==0&&(b[n]=s),s!==0&&(i[s]=n),r===y&&(y=s),r===d&&(d=n),u--,!0},evict:e=>{for(var r=Math.min(e,u);r>0;)A(),r--},clear(){for(var e of m.values())t==null||t(l[e],f[e]);m.clear(),l.fill(void 0),f.fill(void 0),h=[],u=0,y=d=0},resize:e=>{if(!(Number.isInteger(e)&&e>0))throw new TypeError("`max` must be a positive integer");if(e!==v){if(e<v){for(var r=d,n=Math.min(u,e),s=u-n,g=new Array(e),I=new Array(e),K=new Array(e),V=new Array(e),a=1;a<=s;a++)t==null||t(l[a],f[a]);for(var a=n-1;a>=0;a--)g[a]=l[r],I[a]=f[r],K[a]=a+1,V[a]=a-1,m.set(g[a],a),r=i[r];y=0,d=n-1,u=n,l.length=e,f.length=e,b.length=e,i.length=e;for(var a=0;a<n;a++)l[a]=g[a],f[a]=I[a],b[a]=K[a],i[a]=V[a];h=[];for(var a=n;a<e;a++)h.push(a)}else{var p=e-v;l.push(...new Array(p).fill(void 0)),f.push(...new Array(p).fill(void 0)),b.push(...new Array(p).fill(0)),i.push(...new Array(p).fill(0))}v=e}},get max(){return v},get size(){return u},get available(){return v-u}}}; | ||
var createLRU=k=>{var{max:v,onEviction:t}=k;if(!(Number.isInteger(v)&&v>0))throw new TypeError("`max` must be a positive integer");var u=0,y=0,d=0,b=[],h=new Map,l=new Array(v).fill(void 0),f=new Array(v).fill(void 0),m=new Array(v).fill(0),i=new Array(v).fill(0),o=(e,r)=>{if(e!==d){var n=m[e],s=i[e];e===y?y=n:(r==="get"||s!==0)&&(m[s]=n),n!==0&&(i[n]=s),m[d]=e,i[e]=d,m[e]=0,d=e}},K=()=>{var e=y,r=l[e];return t==null||t(r,f[e]),h.delete(r),l[e]=void 0,f[e]=void 0,y=m[e],y!==0&&(i[y]=0),u--,u===0&&(y=d=0),b.push(e),e};return{set(e,r){if(e!==void 0){var n=h.get(e);n===void 0?(n=u===v?K():b.length>0?b.pop():u,h.set(e,n),l[n]=e,u++):t==null||t(e,f[n]),f[n]=r,u===1?y=d=n:o(n,"set")}},get(e){var r=h.get(e);if(r!==void 0)return r!==d&&o(r,"get"),f[r]},peek:e=>{var r=h.get(e);return r!==void 0?f[r]:void 0},has:e=>h.has(e),*keys(){for(var e=d,r=0;r<u;r++)yield l[e],e=i[e]},*values(){for(var e=d,r=0;r<u;r++)yield f[e],e=i[e]},*entries(){for(var e=d,r=0;r<u;r++)yield[l[e],f[e]],e=i[e]},forEach:e=>{for(var r=d,n=0;n<u;n++){var s=l[r],g=f[r];e(g,s),r=i[r]}},delete(e){var r=h.get(e);if(r===void 0)return!1;t==null||t(e,f[r]),h.delete(e),b.push(r),l[r]=void 0,f[r]=void 0;var n=i[r],s=m[r];return n!==0&&(m[n]=s),s!==0&&(i[s]=n),r===y&&(y=s),r===d&&(d=n),u--,!0},evict:e=>{for(var r=Math.min(e,u);r>0;)K(),r--},clear(){for(var e of h.values())t==null||t(l[e],f[e]);h.clear(),l.fill(void 0),f.fill(void 0),b=[],u=0,y=d=0},resize:e=>{if(!(Number.isInteger(e)&&e>0))throw new TypeError("`max` must be a positive integer");if(e!==v){if(e<v){for(var r=d,n=Math.min(u,e),s=u-n,g=new Array(e),A=new Array(e),I=new Array(e),V=new Array(e),a=1;a<=s;a++)t==null||t(l[a],f[a]);for(var a=n-1;a>=0;a--)g[a]=l[r],A[a]=f[r],I[a]=a+1,V[a]=a-1,h.set(g[a],a),r=i[r];y=0,d=n-1,u=n,l.length=e,f.length=e,m.length=e,i.length=e;for(var a=0;a<n;a++)l[a]=g[a],f[a]=A[a],m[a]=I[a],i[a]=V[a];b=[];for(var a=n;a<e;a++)b.push(a)}else{var p=e-v;l.push(...new Array(p).fill(void 0)),f.push(...new Array(p).fill(void 0)),m.push(...new Array(p).fill(0)),i.push(...new Array(p).fill(0))}v=e}},get max(){return v},get size(){return u},get available(){return v-u}}}; |
@@ -1,2 +0,2 @@ | ||
export declare const createLRU: <Key, Value>(options: { | ||
export type CacheOptions<Key = unknown, Value = unknown> = { | ||
/** Maximum number of items the cache can hold. */ | ||
@@ -6,3 +6,4 @@ max: number; | ||
onEviction?: (key: Key, value: Value) => unknown; | ||
}) => { | ||
}; | ||
export declare const createLRU: <Key, Value>(options: CacheOptions<Key, Value>) => { | ||
/** Adds a key-value pair to the cache. Updates the value if the key already exists. */ | ||
@@ -16,9 +17,9 @@ set(key: Key, value: Value): undefined; | ||
has: (key: Key) => boolean; | ||
/** Iterates over all keys in the cache, from least recent to most recent. */ | ||
/** Iterates over all keys in the cache, from most recent to least recent. */ | ||
keys(): IterableIterator<Key>; | ||
/** Iterates over all values in the cache, from least recent to most recent. */ | ||
/** Iterates over all values in the cache, from most recent to least recent. */ | ||
values(): IterableIterator<Value>; | ||
/** Iterates over `[key, value]` pairs in the cache, from least recent to most recent. */ | ||
/** Iterates over `[key, value]` pairs in the cache, from most recent to least recent. */ | ||
entries(): IterableIterator<[Key, Value]>; | ||
/** Iterates over each key-value pair in the cache, from most recent to least recent. */ | ||
/** Iterates over each value-key pair in the cache, from most recent to least recent. */ | ||
forEach: (callback: (value: Value, key: Key) => unknown) => undefined; | ||
@@ -25,0 +26,0 @@ /** Deletes a key-value pair from the cache. */ |
@@ -85,3 +85,3 @@ "use strict"; | ||
has: (key) => keyMap.has(key), | ||
/** Iterates over all keys in the cache, from least recent to most recent. */ | ||
/** Iterates over all keys in the cache, from most recent to least recent. */ | ||
*keys() { | ||
@@ -94,3 +94,3 @@ let current = tail; | ||
}, | ||
/** Iterates over all values in the cache, from least recent to most recent. */ | ||
/** Iterates over all values in the cache, from most recent to least recent. */ | ||
*values() { | ||
@@ -103,3 +103,3 @@ let current = tail; | ||
}, | ||
/** Iterates over `[key, value]` pairs in the cache, from least recent to most recent. */ | ||
/** Iterates over `[key, value]` pairs in the cache, from most recent to least recent. */ | ||
*entries() { | ||
@@ -112,3 +112,3 @@ let current = tail; | ||
}, | ||
/** Iterates over each key-value pair in the cache, from most recent to least recent. */ | ||
/** Iterates over each value-key pair in the cache, from most recent to least recent. */ | ||
forEach: (callback) => { | ||
@@ -115,0 +115,0 @@ let current = tail; |
{ | ||
"name": "lru.min", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "π₯ An extremely fast and efficient LRU cache for JavaScript (Browser compatible) β 6.7KB.", | ||
@@ -51,3 +51,2 @@ "main": "./lib/index.js", | ||
"esbuild": "^0.23.1", | ||
"happy-dom": "^15.0.0", | ||
"monocart-coverage-reports": "^2.10.3", | ||
@@ -54,0 +53,0 @@ "packages-update": "^2.0.0", |
155
README.md
@@ -5,3 +5,3 @@ <h1 align="center">lru.min</h1> | ||
[![NPM Version](https://img.shields.io/npm/v/lru.min.svg?label=&color=70a1ff&logo=npm&logoColor=white)](https://www.npmjs.com/package/lru.min) | ||
[![Coverage](https://img.shields.io/codecov/c/github/wellwelwel/lru.min?label=&logo=codecov&logoColor=white&color=98cc00)](https://github.com/wellwelwel/lru.min/tree/main/.nycrc)<br /> | ||
[![Coverage](https://img.shields.io/codecov/c/github/wellwelwel/lru.min?label=&logo=codecov&logoColor=white&color=98cc00)](https://app.codecov.io/gh/wellwelwel/lru.min)<br /> | ||
[![GitHub Workflow Status (Node.js)](https://img.shields.io/github/actions/workflow/status/wellwelwel/lru.min/ci_node.yml?event=push&label=&branch=main&logo=nodedotjs&logoColor=535c68&color=badc58)](https://github.com/wellwelwel/lru.min/actions/workflows/ci_node.yml?query=branch%3Amain) | ||
@@ -17,3 +17,3 @@ [![GitHub Workflow Status (Bun)](https://img.shields.io/github/actions/workflow/status/wellwelwel/lru.min/ci_bun.yml?event=push&label=&branch=main&logo=bun&logoColor=ffffff&color=f368e0)](https://github.com/wellwelwel/lru.min/actions/workflows/ci_bun.yml?query=branch%3Amain) | ||
- ποΈ **lru.min** is fully compatible with both **Node.js** _(8+)_, **Bun**, **Deno** and, browser environments. All of this, while maintaining the same high performance _(and a little more)_. | ||
- ποΈ **lru.min** is fully compatible with both **Node.js** _(8+)_, **Bun**, **Deno** and, browser environments. All of this, while maintaining the same high performance [_(and a little more)_](https://github.com/wellwelwel/lru.min?tab=readme-ov-file#performance). | ||
@@ -43,2 +43,50 @@ --- | ||
### Quickstart | ||
```js | ||
import { createLRU } from 'lru.min'; | ||
const max = 2; | ||
const onEviction = (key, value) => { | ||
console.log(`Key "${key}" with value "${value}" has been evicted.`); | ||
}; | ||
const LRU = createLRU({ | ||
max, | ||
onEviction, | ||
}); | ||
LRU.set('A', 'My Value'); | ||
LRU.set('B', 'Other Value'); | ||
LRU.set('C', 'Another Value'); | ||
// => Key "A" with value "My Value" has been evicted. | ||
LRU.has('B'); | ||
LRU.get('B'); | ||
LRU.delete('B'); | ||
// => Key "B" with value "Other Value" has been evicted. | ||
LRU.peek('C'); | ||
LRU.clear(); // LRU.evict(max) | ||
// => Key "C" with value "Another Value" has been evicted. | ||
LRU.set('D', "You're amazing π"); | ||
LRU.size; // 1 | ||
LRU.max; // 2 | ||
LRU.available; // 1 | ||
LRU.resize(10); | ||
LRU.size; // 1 | ||
LRU.max; // 10 | ||
LRU.available; // 9 | ||
``` | ||
> For _up-to-date_ documentation, always follow the [**README.md**](https://github.com/wellwelwel/lru.min?tab=readme-ov-file#readme) in the **GitHub** repository. | ||
### Import | ||
@@ -69,4 +117,2 @@ | ||
```ts | ||
import { createLRU } from 'lru.min'; | ||
const LRU = createLRU({ max: 150_000 }); | ||
@@ -109,3 +155,3 @@ ``` | ||
```ts | ||
LRU.get('key'); | ||
LRU.peek('key'); | ||
``` | ||
@@ -133,2 +179,7 @@ | ||
> [!TIP] | ||
> | ||
> - Methods that perform eviction(s) when maximum size is reached: `set` and `resize`. | ||
> - Methods that always perform eviction(s): `delete`, `clear`, and `evict` itself. | ||
### Resize the cache | ||
@@ -170,5 +221,7 @@ | ||
### Iterating the cache | ||
#### Get all keys | ||
Iterates over all keys in the cache, from least recent to most recent. | ||
Iterates over all keys in the cache, from most recent to least recent. | ||
@@ -181,6 +234,6 @@ ```ts | ||
Iterates over all values in the cache, from least recent to most recent. | ||
Iterates over all values in the cache, from most recent to least recent. | ||
```ts | ||
const keys = [...LRU.values()]; | ||
const values = [...LRU.values()]; | ||
``` | ||
@@ -190,3 +243,3 @@ | ||
Iterates over `[key, value]` pairs in the cache, from least recent to most recent. | ||
Iterates over `[key, value]` pairs in the cache, from most recent to least recent. | ||
@@ -197,20 +250,56 @@ ```ts | ||
#### Get all entries | ||
#### Run a callback for each entry | ||
Iterates over `[key, value]` pairs in the cache, from least recent to most recent. | ||
Iterates over each value-key pair in the cache, from most recent to least recent. | ||
```ts | ||
const entries = [...LRU.entries()]; | ||
LRU.forEach((value, key) => { | ||
// do something | ||
}); | ||
``` | ||
#### Run a callback for each entry | ||
### TypeScript | ||
Iterates over each key-value pair in the cache, from most recent to least recent. | ||
You can set types for both keys and values. For example: | ||
```ts | ||
LRU.forEach((value, key) => { | ||
// do something | ||
}); | ||
import { createLRU } from 'lru.min'; | ||
type Key = number; | ||
type Value = { | ||
name: string; | ||
}; | ||
const LRU = createLRU<Key, Value>({ max: 1000 }); | ||
LRU.set(1, { name: 'Peter' }); | ||
LRU.set(2, { name: 'Mary' }); | ||
``` | ||
Also: | ||
```ts | ||
import { createLRU, type CacheOptions } from 'lru.min'; | ||
type Key = number; | ||
type Value = { | ||
name: string; | ||
}; | ||
const options: CacheOptions<Key, Value> = { | ||
max: 10, | ||
onEviction(key, value) { | ||
console.log(key, value); | ||
}, | ||
}; | ||
// No need to repeat the type params | ||
const LRU = createLRU(options); | ||
LRU.set(1, { name: 'Peter' }); | ||
LRU.set(2, { name: 'Mary' }); | ||
``` | ||
--- | ||
@@ -259,3 +348,3 @@ | ||
> For more comprehensive features such as **TTL** support, consider using and supporting them π€ | ||
For more comprehensive features such as **TTL** support, consider using and supporting them π€ | ||
@@ -268,2 +357,32 @@ - The architecture is mostly based on [@isaacs](https://github.com/isaacs) β [**lru-cache**](https://github.com/isaacs/node-lru-cache/blob/8f51d75351cbb4ac819952eb8e9f95eda00ef800/src/index.ts). | ||
#### What comes from [**lru-cache**](https://github.com/isaacs/node-lru-cache)? | ||
Architecture's essence: | ||
> _It's not the same code, but majority based on [this](https://github.com/isaacs/node-lru-cache/blob/8f51d75351cbb4ac819952eb8e9f95eda00ef800/src/index.ts#L1385-L1394)._ | ||
```ts | ||
let free: number[] = []; | ||
const keyMap: Map<Key, number> = new Map(); | ||
const keyList: (Key | undefined)[] = new Array(max).fill(undefined); | ||
const valList: (Value | undefined)[] = new Array(max).fill(undefined); | ||
const next: number[] = new Array(max).fill(0); | ||
const prev: number[] = new Array(max).fill(0); | ||
``` | ||
--- | ||
#### What comes from [**quick-lru**](https://github.com/sindresorhus/quick-lru)? | ||
Name of methods and options _(including their final functionality ideas)_: | ||
- `resize` | ||
- `peek` | ||
- `onEviction` | ||
- `forEach` | ||
- `entriesDescending` as `entries` | ||
--- | ||
## License | ||
@@ -270,0 +389,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32625
9
475
380