Upgrade octokit to v4.1.2

This commit is contained in:
Angela P Wen 2025-02-19 11:13:12 -08:00
parent dbbcbe019d
commit c1745a9831
1214 changed files with 160765 additions and 0 deletions

21
node_modules/toad-cache/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Igor Savin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

265
node_modules/toad-cache/README.md generated vendored Normal file
View file

@ -0,0 +1,265 @@
# Toad Cache
[![NPM Version](https://img.shields.io/npm/v/toad-cache.svg)](https://npmjs.org/package/toad-cache)
[![NPM Downloads](https://img.shields.io/npm/dm/toad-cache.svg)](https://npmjs.org/package/toad-cache)
![](https://github.com/kibertoad/toad-cache/workflows/ci/badge.svg)
[![Coverage Status](https://coveralls.io/repos/kibertoad/toad-cache/badge.svg?branch=main)](https://coveralls.io/r/kibertoad/toad-cache?branch=main)
Least-Recently-Used and First-In-First-Out caches for Client or Server.
## Getting started
```javascript
import { Lru, Fifo } from 'toad-cache'
const lruCache = new Lru(max, ttl = 0)
const fifoCache = new Fifo(max, ttl = 0)
```
## clear
### Method
Clears the contents of the cache
**Example**
```javascript
cache.clear()
```
## delete
### Method
Removes item from cache
param {String} key Item key
**Example**
```javascript
cache.delete('myKey')
```
## deleteMany
### Method
Removes items from cache
param {String[]} keys Item keys
**Example**
```javascript
cache.deleteMany(['myKey', 'myKey2'])
```
## evict
### Method
Evicts the least recently used item from cache
**Example**
```javascript
cache.evict()
```
## expiresAt
### Method
Gets expiration time for cached item
param {String} key Item key
return {Mixed} Undefined or number (epoch time)
**Example**
```javascript
const item = cache.expiresAt('myKey')
```
## first
### Property
Item in "first" or "bottom" position
**Example**
```javascript
const cache = new Lru()
cache.first // null - it's a new cache!
```
## get
### Method
Gets cached item and marks it as recently used (pushes to the back of the list of the candidates for the eviction)
param {String} key Item key
return {Mixed} Undefined or Item value
**Example**
```javascript
const item = cache.get('myKey')
```
## getMany
### Method
Gets multiple cached items and marks them as recently used (pushes to the back of the list of the candidates for the eviction)
param {String[]} keys Item keys
return {Mixed[]} Undefined or Item values
**Example**
```javascript
const item = cache.getMany(['myKey', 'myKey2'])
```
## keys
### Method
Returns an `Array` of cache item keys.
return {Array} Array of keys
**Example**
```javascript
console.log(cache.keys())
```
## max
### Property
Max items to hold in cache (1000)
**Example**
```javascript
const cache = new Lru(500)
cache.max // 500
```
## last
### Property
Item in "last" or "top" position
**Example**
```javascript
const cache = new Lru()
cache.last // null - it's a new cache!
```
## set
### Method
Sets item in cache as `first`
param {String} key Item key
param {Mixed} value Item value
**Example**
```javascript
cache.set('myKey', { prop: true })
```
## size
### Property
Number of items in cache
**Example**
```javascript
const cache = new Lru()
cache.size // 0 - it's a new cache!
```
## ttl
### Property
Milliseconds an item will remain in cache; lazy expiration upon next `get()` of an item
**Example**
```javascript
const cache = new Lru()
cache.ttl = 3e4
```
## Hit/miss/expiration tracking
In case you want to gather information on cache hit/miss/expiration ratio, as well as cache size and eviction statistics, you can use LruHitStatistics class:
```js
const sharedRecord = new HitStatisticsRecord() // if you want to use single record object for all of caches, create it manually and pass to each cache
const cache = new LruHitStatistics({
cacheId: 'some-cache-id',
globalStatisticsRecord: sharedRecord,
statisticTtlInHours: 24, // how often to reset statistics. On every rotation previously accumulated data is removed
max: 1000,
ttlInMsecs: 0,
})
```
You can retrieve accumulated statistics from the cache, or from the record directly:
```js
// this is the same
const statistics = sharedRecord.getStatistics()
const alsoStatistics = cache.getStatistics()
/*
{
'some-cache-id': {
'2023-04-06': {
cacheSize: 100, // how many elements does cache currently have
evictions: 5, // how many elements were evicted due to cache being at max capacity
expirations: 0, // how many elements were removed during get due to their ttl being exceeded
hits: 0, // how many times element was successfully retrieved from cache during get
emptyHits: 0, // out of all hits, how many were null, undefined or ''?
falsyHits: 0, // out of all hits, how many were falsy?
misses: 1, // how many times element was not in cache or expired during get
invalidateOne: 1, // how many times element was invalidated individually
invalidateAll: 2, // how many times entire cache was invalidated
sets: 0, // how many times new element was added
},
},
}
Note that date here reflects start of the rotation. If statistics weren't rotated yet, and another day started, it will still be counted against the day of the rotation start
*/
```
## License
Copyright (c) 2023 Igor Savin
Based on [tiny-lru](https://github.com/avoidwork/tiny-lru), created by Jason Mulligan
Licensed under the MIT license.

878
node_modules/toad-cache/dist/toad-cache.cjs generated vendored Normal file
View file

@ -0,0 +1,878 @@
/**
* toad-cache
*
* @copyright 2024 Igor Savin <kibertoad@gmail.com>
* @license MIT
* @version 3.7.0
*/
'use strict';
class FifoMap {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = new Map();
this.last = null;
this.max = max;
this.ttl = ttlInMsecs;
}
get size() {
return this.items.size
}
clear() {
this.items = new Map();
this.first = null;
this.last = null;
}
delete(key) {
if (this.items.has(key)) {
const deletedItem = this.items.get(key);
this.items.delete(key);
if (deletedItem.prev !== null) {
deletedItem.prev.next = deletedItem.next;
}
if (deletedItem.next !== null) {
deletedItem.next.prev = deletedItem.prev;
}
if (this.first === deletedItem) {
this.first = deletedItem.next;
}
if (this.last === deletedItem) {
this.last = deletedItem.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
this.items.delete(item.key);
if (this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (this.items.has(key)) {
return this.items.get(key).expiry
}
}
get(key) {
if (this.items.has(key)) {
const item = this.items.get(key);
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return this.items.keys()
}
set(key, value) {
// Replace existing item
if (this.items.has(key)) {
const item = this.items.get(key);
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items.set(key, item);
if (this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}
class LruMap {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = new Map();
this.last = null;
this.max = max;
this.ttl = ttlInMsecs;
}
get size() {
return this.items.size
}
bumpLru(item) {
if (this.last === item) {
return // Item is already the last one, no need to bump
}
const last = this.last;
const next = item.next;
const prev = item.prev;
if (this.first === item) {
this.first = next;
}
item.next = null;
item.prev = last;
last.next = item;
if (prev !== null) {
prev.next = next;
}
if (next !== null) {
next.prev = prev;
}
this.last = item;
}
clear() {
this.items = new Map();
this.first = null;
this.last = null;
}
delete(key) {
if (this.items.has(key)) {
const item = this.items.get(key);
this.items.delete(key);
if (item.prev !== null) {
item.prev.next = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
}
if (this.first === item) {
this.first = item.next;
}
if (this.last === item) {
this.last = item.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
this.items.delete(item.key);
if (this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (this.items.has(key)) {
return this.items.get(key).expiry
}
}
get(key) {
if (this.items.has(key)) {
const item = this.items.get(key);
// Item has already expired
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
// Item is still fresh
this.bumpLru(item);
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return this.items.keys()
}
set(key, value) {
// Replace existing item
if (this.items.has(key)) {
const item = this.items.get(key);
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
if (this.last !== item) {
this.bumpLru(item);
}
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items.set(key, item);
if (this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}
class LruObject {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = Object.create(null);
this.last = null;
this.size = 0;
this.max = max;
this.ttl = ttlInMsecs;
}
bumpLru(item) {
if (this.last === item) {
return // Item is already the last one, no need to bump
}
const last = this.last;
const next = item.next;
const prev = item.prev;
if (this.first === item) {
this.first = next;
}
item.next = null;
item.prev = last;
last.next = item;
if (prev !== null) {
prev.next = next;
}
if (next !== null) {
next.prev = prev;
}
this.last = item;
}
clear() {
this.items = Object.create(null);
this.first = null;
this.last = null;
this.size = 0;
}
delete(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
delete this.items[key];
this.size--;
if (item.prev !== null) {
item.prev.next = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
}
if (this.first === item) {
this.first = item.next;
}
if (this.last === item) {
this.last = item.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
delete this.items[item.key];
if (--this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
return this.items[key].expiry
}
}
get(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
// Item has already expired
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
// Item is still fresh
this.bumpLru(item);
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return Object.keys(this.items)
}
set(key, value) {
// Replace existing item
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
if (this.last !== item) {
this.bumpLru(item);
}
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items[key] = item;
if (++this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}
class HitStatisticsRecord {
constructor() {
this.records = {};
}
initForCache(cacheId, currentTimeStamp) {
this.records[cacheId] = {
[currentTimeStamp]: {
cacheSize: 0,
hits: 0,
falsyHits: 0,
emptyHits: 0,
misses: 0,
expirations: 0,
evictions: 0,
invalidateOne: 0,
invalidateAll: 0,
sets: 0,
},
};
}
resetForCache(cacheId) {
for (let key of Object.keys(this.records[cacheId])) {
this.records[cacheId][key] = {
cacheSize: 0,
hits: 0,
falsyHits: 0,
emptyHits: 0,
misses: 0,
expirations: 0,
evictions: 0,
invalidateOne: 0,
invalidateAll: 0,
sets: 0,
};
}
}
getStatistics() {
return this.records
}
}
/**
*
* @param {Date} date
* @returns {string}
*/
function getTimestamp(date) {
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
.getDate()
.toString()
.padStart(2, '0')}`
}
class HitStatistics {
constructor(cacheId, statisticTtlInHours, globalStatisticsRecord) {
this.cacheId = cacheId;
this.statisticTtlInHours = statisticTtlInHours;
this.collectionStart = new Date();
this.currentTimeStamp = getTimestamp(this.collectionStart);
this.records = globalStatisticsRecord || new HitStatisticsRecord();
this.records.initForCache(this.cacheId, this.currentTimeStamp);
}
get currentRecord() {
// safety net
/* c8 ignore next 14 */
if (!this.records.records[this.cacheId][this.currentTimeStamp]) {
this.records.records[this.cacheId][this.currentTimeStamp] = {
cacheSize: 0,
hits: 0,
falsyHits: 0,
emptyHits: 0,
misses: 0,
expirations: 0,
evictions: 0,
sets: 0,
invalidateOne: 0,
invalidateAll: 0,
};
}
return this.records.records[this.cacheId][this.currentTimeStamp]
}
hoursPassed() {
return (Date.now() - this.collectionStart) / 1000 / 60 / 60
}
addHit() {
this.archiveIfNeeded();
this.currentRecord.hits++;
}
addFalsyHit() {
this.archiveIfNeeded();
this.currentRecord.falsyHits++;
}
addEmptyHit() {
this.archiveIfNeeded();
this.currentRecord.emptyHits++;
}
addMiss() {
this.archiveIfNeeded();
this.currentRecord.misses++;
}
addEviction() {
this.archiveIfNeeded();
this.currentRecord.evictions++;
}
setCacheSize(currentSize) {
this.archiveIfNeeded();
this.currentRecord.cacheSize = currentSize;
}
addExpiration() {
this.archiveIfNeeded();
this.currentRecord.expirations++;
}
addSet() {
this.archiveIfNeeded();
this.currentRecord.sets++;
}
addInvalidateOne() {
this.archiveIfNeeded();
this.currentRecord.invalidateOne++;
}
addInvalidateAll() {
this.archiveIfNeeded();
this.currentRecord.invalidateAll++;
}
getStatistics() {
return this.records.getStatistics()
}
archiveIfNeeded() {
if (this.hoursPassed() >= this.statisticTtlInHours) {
this.collectionStart = new Date();
this.currentTimeStamp = getTimestamp(this.collectionStart);
this.records.initForCache(this.cacheId, this.currentTimeStamp);
}
}
}
class LruObjectHitStatistics extends LruObject {
constructor(max, ttlInMsecs, cacheId, globalStatisticsRecord, statisticTtlInHours) {
super(max || 1000, ttlInMsecs || 0);
if (!cacheId) {
throw new Error('Cache id is mandatory')
}
this.hitStatistics = new HitStatistics(
cacheId,
statisticTtlInHours !== undefined ? statisticTtlInHours : 24,
globalStatisticsRecord,
);
}
getStatistics() {
return this.hitStatistics.getStatistics()
}
set(key, value) {
super.set(key, value);
this.hitStatistics.addSet();
this.hitStatistics.setCacheSize(this.size);
}
evict() {
super.evict();
this.hitStatistics.addEviction();
this.hitStatistics.setCacheSize(this.size);
}
delete(key, isExpiration = false) {
super.delete(key);
if (!isExpiration) {
this.hitStatistics.addInvalidateOne();
}
this.hitStatistics.setCacheSize(this.size);
}
clear() {
super.clear();
this.hitStatistics.addInvalidateAll();
this.hitStatistics.setCacheSize(this.size);
}
get(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
// Item has already expired
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key, true);
this.hitStatistics.addExpiration();
return
}
// Item is still fresh
this.bumpLru(item);
if (!item.value) {
this.hitStatistics.addFalsyHit();
}
if (item.value === undefined || item.value === null || item.value === '') {
this.hitStatistics.addEmptyHit();
}
this.hitStatistics.addHit();
return item.value
}
this.hitStatistics.addMiss();
}
}
class FifoObject {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = Object.create(null);
this.last = null;
this.size = 0;
this.max = max;
this.ttl = ttlInMsecs;
}
clear() {
this.items = Object.create(null);
this.first = null;
this.last = null;
this.size = 0;
}
delete(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const deletedItem = this.items[key];
delete this.items[key];
this.size--;
if (deletedItem.prev !== null) {
deletedItem.prev.next = deletedItem.next;
}
if (deletedItem.next !== null) {
deletedItem.next.prev = deletedItem.prev;
}
if (this.first === deletedItem) {
this.first = deletedItem.next;
}
if (this.last === deletedItem) {
this.last = deletedItem.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
delete this.items[item.key];
if (--this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
return this.items[key].expiry
}
}
get(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return Object.keys(this.items)
}
set(key, value) {
// Replace existing item
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items[key] = item;
if (++this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}
exports.Fifo = FifoObject;
exports.FifoMap = FifoMap;
exports.FifoObject = FifoObject;
exports.HitStatisticsRecord = HitStatisticsRecord;
exports.Lru = LruObject;
exports.LruHitStatistics = LruObjectHitStatistics;
exports.LruMap = LruMap;
exports.LruObject = LruObject;
exports.LruObjectHitStatistics = LruObjectHitStatistics;

852
node_modules/toad-cache/dist/toad-cache.mjs generated vendored Normal file
View file

@ -0,0 +1,852 @@
/**
* toad-cache
*
* @copyright 2024 Igor Savin <kibertoad@gmail.com>
* @license MIT
* @version 3.7.0
*/
class FifoMap {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = new Map();
this.last = null;
this.max = max;
this.ttl = ttlInMsecs;
}
get size() {
return this.items.size
}
clear() {
this.items = new Map();
this.first = null;
this.last = null;
}
delete(key) {
if (this.items.has(key)) {
const deletedItem = this.items.get(key);
this.items.delete(key);
if (deletedItem.prev !== null) {
deletedItem.prev.next = deletedItem.next;
}
if (deletedItem.next !== null) {
deletedItem.next.prev = deletedItem.prev;
}
if (this.first === deletedItem) {
this.first = deletedItem.next;
}
if (this.last === deletedItem) {
this.last = deletedItem.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
this.items.delete(item.key);
if (this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (this.items.has(key)) {
return this.items.get(key).expiry
}
}
get(key) {
if (this.items.has(key)) {
const item = this.items.get(key);
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return this.items.keys()
}
set(key, value) {
// Replace existing item
if (this.items.has(key)) {
const item = this.items.get(key);
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items.set(key, item);
if (this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}class LruMap {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = new Map();
this.last = null;
this.max = max;
this.ttl = ttlInMsecs;
}
get size() {
return this.items.size
}
bumpLru(item) {
if (this.last === item) {
return // Item is already the last one, no need to bump
}
const last = this.last;
const next = item.next;
const prev = item.prev;
if (this.first === item) {
this.first = next;
}
item.next = null;
item.prev = last;
last.next = item;
if (prev !== null) {
prev.next = next;
}
if (next !== null) {
next.prev = prev;
}
this.last = item;
}
clear() {
this.items = new Map();
this.first = null;
this.last = null;
}
delete(key) {
if (this.items.has(key)) {
const item = this.items.get(key);
this.items.delete(key);
if (item.prev !== null) {
item.prev.next = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
}
if (this.first === item) {
this.first = item.next;
}
if (this.last === item) {
this.last = item.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
this.items.delete(item.key);
if (this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (this.items.has(key)) {
return this.items.get(key).expiry
}
}
get(key) {
if (this.items.has(key)) {
const item = this.items.get(key);
// Item has already expired
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
// Item is still fresh
this.bumpLru(item);
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return this.items.keys()
}
set(key, value) {
// Replace existing item
if (this.items.has(key)) {
const item = this.items.get(key);
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
if (this.last !== item) {
this.bumpLru(item);
}
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items.set(key, item);
if (this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}class LruObject {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = Object.create(null);
this.last = null;
this.size = 0;
this.max = max;
this.ttl = ttlInMsecs;
}
bumpLru(item) {
if (this.last === item) {
return // Item is already the last one, no need to bump
}
const last = this.last;
const next = item.next;
const prev = item.prev;
if (this.first === item) {
this.first = next;
}
item.next = null;
item.prev = last;
last.next = item;
if (prev !== null) {
prev.next = next;
}
if (next !== null) {
next.prev = prev;
}
this.last = item;
}
clear() {
this.items = Object.create(null);
this.first = null;
this.last = null;
this.size = 0;
}
delete(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
delete this.items[key];
this.size--;
if (item.prev !== null) {
item.prev.next = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
}
if (this.first === item) {
this.first = item.next;
}
if (this.last === item) {
this.last = item.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
delete this.items[item.key];
if (--this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
return this.items[key].expiry
}
}
get(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
// Item has already expired
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
// Item is still fresh
this.bumpLru(item);
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return Object.keys(this.items)
}
set(key, value) {
// Replace existing item
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
if (this.last !== item) {
this.bumpLru(item);
}
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items[key] = item;
if (++this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}class HitStatisticsRecord {
constructor() {
this.records = {};
}
initForCache(cacheId, currentTimeStamp) {
this.records[cacheId] = {
[currentTimeStamp]: {
cacheSize: 0,
hits: 0,
falsyHits: 0,
emptyHits: 0,
misses: 0,
expirations: 0,
evictions: 0,
invalidateOne: 0,
invalidateAll: 0,
sets: 0,
},
};
}
resetForCache(cacheId) {
for (let key of Object.keys(this.records[cacheId])) {
this.records[cacheId][key] = {
cacheSize: 0,
hits: 0,
falsyHits: 0,
emptyHits: 0,
misses: 0,
expirations: 0,
evictions: 0,
invalidateOne: 0,
invalidateAll: 0,
sets: 0,
};
}
}
getStatistics() {
return this.records
}
}/**
*
* @param {Date} date
* @returns {string}
*/
function getTimestamp(date) {
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
.getDate()
.toString()
.padStart(2, '0')}`
}class HitStatistics {
constructor(cacheId, statisticTtlInHours, globalStatisticsRecord) {
this.cacheId = cacheId;
this.statisticTtlInHours = statisticTtlInHours;
this.collectionStart = new Date();
this.currentTimeStamp = getTimestamp(this.collectionStart);
this.records = globalStatisticsRecord || new HitStatisticsRecord();
this.records.initForCache(this.cacheId, this.currentTimeStamp);
}
get currentRecord() {
// safety net
/* c8 ignore next 14 */
if (!this.records.records[this.cacheId][this.currentTimeStamp]) {
this.records.records[this.cacheId][this.currentTimeStamp] = {
cacheSize: 0,
hits: 0,
falsyHits: 0,
emptyHits: 0,
misses: 0,
expirations: 0,
evictions: 0,
sets: 0,
invalidateOne: 0,
invalidateAll: 0,
};
}
return this.records.records[this.cacheId][this.currentTimeStamp]
}
hoursPassed() {
return (Date.now() - this.collectionStart) / 1000 / 60 / 60
}
addHit() {
this.archiveIfNeeded();
this.currentRecord.hits++;
}
addFalsyHit() {
this.archiveIfNeeded();
this.currentRecord.falsyHits++;
}
addEmptyHit() {
this.archiveIfNeeded();
this.currentRecord.emptyHits++;
}
addMiss() {
this.archiveIfNeeded();
this.currentRecord.misses++;
}
addEviction() {
this.archiveIfNeeded();
this.currentRecord.evictions++;
}
setCacheSize(currentSize) {
this.archiveIfNeeded();
this.currentRecord.cacheSize = currentSize;
}
addExpiration() {
this.archiveIfNeeded();
this.currentRecord.expirations++;
}
addSet() {
this.archiveIfNeeded();
this.currentRecord.sets++;
}
addInvalidateOne() {
this.archiveIfNeeded();
this.currentRecord.invalidateOne++;
}
addInvalidateAll() {
this.archiveIfNeeded();
this.currentRecord.invalidateAll++;
}
getStatistics() {
return this.records.getStatistics()
}
archiveIfNeeded() {
if (this.hoursPassed() >= this.statisticTtlInHours) {
this.collectionStart = new Date();
this.currentTimeStamp = getTimestamp(this.collectionStart);
this.records.initForCache(this.cacheId, this.currentTimeStamp);
}
}
}class LruObjectHitStatistics extends LruObject {
constructor(max, ttlInMsecs, cacheId, globalStatisticsRecord, statisticTtlInHours) {
super(max || 1000, ttlInMsecs || 0);
if (!cacheId) {
throw new Error('Cache id is mandatory')
}
this.hitStatistics = new HitStatistics(
cacheId,
statisticTtlInHours !== undefined ? statisticTtlInHours : 24,
globalStatisticsRecord,
);
}
getStatistics() {
return this.hitStatistics.getStatistics()
}
set(key, value) {
super.set(key, value);
this.hitStatistics.addSet();
this.hitStatistics.setCacheSize(this.size);
}
evict() {
super.evict();
this.hitStatistics.addEviction();
this.hitStatistics.setCacheSize(this.size);
}
delete(key, isExpiration = false) {
super.delete(key);
if (!isExpiration) {
this.hitStatistics.addInvalidateOne();
}
this.hitStatistics.setCacheSize(this.size);
}
clear() {
super.clear();
this.hitStatistics.addInvalidateAll();
this.hitStatistics.setCacheSize(this.size);
}
get(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
// Item has already expired
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key, true);
this.hitStatistics.addExpiration();
return
}
// Item is still fresh
this.bumpLru(item);
if (!item.value) {
this.hitStatistics.addFalsyHit();
}
if (item.value === undefined || item.value === null || item.value === '') {
this.hitStatistics.addEmptyHit();
}
this.hitStatistics.addHit();
return item.value
}
this.hitStatistics.addMiss();
}
}class FifoObject {
constructor(max = 1000, ttlInMsecs = 0) {
if (isNaN(max) || max < 0) {
throw new Error('Invalid max value')
}
if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
throw new Error('Invalid ttl value')
}
this.first = null;
this.items = Object.create(null);
this.last = null;
this.size = 0;
this.max = max;
this.ttl = ttlInMsecs;
}
clear() {
this.items = Object.create(null);
this.first = null;
this.last = null;
this.size = 0;
}
delete(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const deletedItem = this.items[key];
delete this.items[key];
this.size--;
if (deletedItem.prev !== null) {
deletedItem.prev.next = deletedItem.next;
}
if (deletedItem.next !== null) {
deletedItem.next.prev = deletedItem.prev;
}
if (this.first === deletedItem) {
this.first = deletedItem.next;
}
if (this.last === deletedItem) {
this.last = deletedItem.prev;
}
}
}
deleteMany(keys) {
for (var i = 0; i < keys.length; i++) {
this.delete(keys[i]);
}
}
evict() {
if (this.size > 0) {
const item = this.first;
delete this.items[item.key];
if (--this.size === 0) {
this.first = null;
this.last = null;
} else {
this.first = item.next;
this.first.prev = null;
}
}
}
expiresAt(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
return this.items[key].expiry
}
}
get(key) {
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
if (this.ttl > 0 && item.expiry <= Date.now()) {
this.delete(key);
return
}
return item.value
}
}
getMany(keys) {
const result = [];
for (var i = 0; i < keys.length; i++) {
result.push(this.get(keys[i]));
}
return result
}
keys() {
return Object.keys(this.items)
}
set(key, value) {
// Replace existing item
if (Object.prototype.hasOwnProperty.call(this.items, key)) {
const item = this.items[key];
item.value = value;
item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
return
}
// Add new item
if (this.max > 0 && this.size === this.max) {
this.evict();
}
const item = {
expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value,
};
this.items[key] = item;
if (++this.size === 1) {
this.first = item;
} else {
this.last.next = item;
}
this.last = item;
}
}export{FifoObject as Fifo,FifoMap,FifoObject,HitStatisticsRecord,LruObject as Lru,LruObjectHitStatistics as LruHitStatistics,LruMap,LruObject,LruObjectHitStatistics};

82
node_modules/toad-cache/package.json generated vendored Normal file
View file

@ -0,0 +1,82 @@
{
"name": "toad-cache",
"description": "LRU and FIFO caches for Client or Server",
"version": "3.7.0",
"homepage": "https://github.com/kibertoad/toad-cache",
"author": "Igor Savin <kibertoad@gmail.com>",
"repository": {
"type": "git",
"url": "git://github.com/kibertoad/toad-cache.git"
},
"bugs": {
"url": "https://github.com/kibertoad/toad-cache/issues"
},
"files": [
"dist",
"*.d.ts",
"*.d.cts"
],
"license": "MIT",
"source": "index.js",
"exports": {
".": {
"import": {
"types": "./toad-cache.d.ts",
"default": "./dist/toad-cache.mjs"
},
"require": {
"types": "./toad-cache.d.cts",
"default": "./dist/toad-cache.cjs"
}
}
},
"main": "dist/toad-cache.cjs",
"types": "./toad-cache.d.ts",
"type": "module",
"sourceType": "module",
"engines": {
"node": ">=12"
},
"engineStrict": true,
"scripts": {
"build": "del-cli dist && del-cli coverage && npm run rollup",
"benchmark": "npm run build && node benchmark.js",
"changelog": "auto-changelog -p",
"lint": "eslint *.js src/*.js test/*.js",
"lint:fix": "eslint --fix *.js src/*.js test/*.js && prettier --write \"{src,test}/**/*.js\" benchmark.js",
"rollup": "rollup --config",
"test": "vitest",
"test:coverage": "npm run rollup && npm run test -- --coverage",
"test:ci": "npm run lint && npm run test:coverage && npm run test:typescript",
"test:typescript": "tsd",
"types:generate": "npx -p typescript tsc index.js --declaration --allowJs --emitDeclarationOnly --outDir .",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"@vitest/coverage-v8": "^1.0.0",
"@rollup/plugin-terser": "^0.4.4",
"auto-changelog": "^2.4.0",
"del-cli": "^5.1.0",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0",
"precise": "^4.0.0",
"rollup": "^4.6.0",
"vitest": "^1.1.3",
"tsd": "^0.30.0",
"typescript": "^5.3.2"
},
"keywords": [
"LRU",
"FIFO",
"cache",
"client",
"server",
"least",
"recently",
"used",
"first",
"browser"
]
}

138
node_modules/toad-cache/toad-cache.d.cts generated vendored Normal file
View file

@ -0,0 +1,138 @@
type CacheConstructor<T> = new (max?: number, ttlInMsecs?: number, cacheId?: string, cacheStatistics?: HitStatisticsRecord) => T
type CacheEntry<T> = {
expiry: number
key: any
prev: CacheEntry<T> | null
next: CacheEntry<T> | null
value: T
}
interface ToadCache<T> {
first: any;
last: any;
max: number;
ttl: number;
size: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
keys(): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
set(key: any, value: T): void;
}
declare class FifoMap<T> implements ToadCache<T>{
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Map<any, T>;
last: any;
max: number;
ttl: number;
size: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): IterableIterator<any>;
set(key: any, value: T): void;
}
declare class FifoObject<T> implements ToadCache<T> {
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Record<any, CacheEntry<T>>;
last: any;
size: number;
max: number;
ttl: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): string[];
set(key: any, value: T): void;
}
declare class LruMap<T> implements ToadCache<T> {
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Map<any, T>;
last: any;
max: number;
ttl: number;
size: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): IterableIterator<any>;
set(key: any, value: T): void;
}
declare class LruObject<T> implements ToadCache<T> {
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Record<any, CacheEntry<T>>;
last: any;
size: number;
max: number;
ttl: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): string[];
set(key: any, value: T): void;
}
declare class HitStatisticsRecord {
records: Record<string, Record<string, {
expirations: number,
evictions: number,
hits: number,
emptyHits: number,
falsyHits: number,
misses: number,
invalidateAll: number,
invalidateOne: number,
cacheSize: number,
sets: number,
}>>
initForCache(cacheId: string, currentTimeStamp: string): void
resetForCache(cacheId: string): void
}
declare class LruObjectHitStatistics<T> extends LruObject<T>{
constructor(max?: number, ttlInMsecs?: number, cacheId?: string, globalStatisticsRecord?: HitStatisticsRecord, statisticTtlInHours?: number);
}
export {
CacheConstructor,
ToadCache,
LruObject,
LruMap,
FifoMap,
FifoObject,
HitStatisticsRecord,
LruObjectHitStatistics,
FifoObject as Fifo,
LruObject as Lru
}

128
node_modules/toad-cache/toad-cache.d.ts generated vendored Normal file
View file

@ -0,0 +1,128 @@
export type CacheConstructor<T> = new (max?: number, ttlInMsecs?: number, cacheId?: string, cacheStatistics?: HitStatisticsRecord) => T
export type CacheEntry<T> = {
expiry: number
key: any
prev: CacheEntry<T> | null
next: CacheEntry<T> | null
value: T
}
export interface ToadCache<T> {
first: any;
last: any;
max: number;
ttl: number;
size: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
keys(): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
set(key: any, value: T): void;
}
export class FifoMap<T> implements ToadCache<T>{
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Map<any, T>;
last: any;
max: number;
ttl: number;
size: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): IterableIterator<any>;
set(key: any, value: T): void;
}
export class FifoObject<T> implements ToadCache<T> {
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Record<any, CacheEntry<T>>;
last: any;
size: number;
max: number;
ttl: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): string[];
set(key: any, value: T): void;
}
export class LruMap<T> implements ToadCache<T> {
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Map<any, T>;
last: any;
max: number;
ttl: number;
size: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): IterableIterator<any>;
set(key: any, value: T): void;
}
export class LruObject<T> implements ToadCache<T> {
constructor(max?: number, ttlInMsecs?: number);
first: any;
items: Record<any, CacheEntry<T>>;
last: any;
size: number;
max: number;
ttl: number;
clear(): void;
delete(key: any): void;
deleteMany(keys: any[]): void;
evict(): void;
expiresAt(key: any): any;
get(key: any): T | undefined;
getMany(keys: any[]): (T | undefined)[];
keys(): string[];
set(key: any, value: T): void;
}
export class HitStatisticsRecord {
records: Record<string, Record<string, {
expirations: number,
evictions: number,
hits: number,
emptyHits: number,
falsyHits: number,
misses: number,
invalidateAll: number,
invalidateOne: number,
cacheSize: number,
sets: number,
}>>
initForCache(cacheId: string, currentTimeStamp: string): void
resetForCache(cacheId: string): void
}
export class LruObjectHitStatistics<T> extends LruObject<T>{
constructor(max?: number, ttlInMsecs?: number, cacheId?: string, globalStatisticsRecord?: HitStatisticsRecord, statisticTtlInHours?: number);
}
export { FifoObject as Fifo }
export { LruObject as Lru }