fix: multi-repo local dev (file:../ deps, package exports, missing deps)

This commit is contained in:
Raven Scott
2026-05-21 20:14:54 -04:00
parent 76e3272ced
commit b63275c6cc
802 changed files with 94636 additions and 4 deletions
+6
View File
@@ -0,0 +1,6 @@
language: node_js
sudo: false
node_js:
- 6
- 8
- 9
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Mathias Buus
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.
+83
View File
@@ -0,0 +1,83 @@
# record-cache
Cache optimised for record like things like `host:port` or `domain.names`.
```
npm install record-cache
```
[![build status](https://travis-ci.org/mafintosh/record-cache.svg?branch=master)](https://travis-ci.org/mafintosh/record-cache)
## Usage
``` js
var recordCache = require('record-cache')
var cache = recordCache({
maxSize: 1000 // store ~1000 values at max
maxAge: 1000 // gc values older than ~1000ms
})
cache.add('hello', '127.0.0.1')
cache.add('hello', '127.0.1.1')
cache.add('hello', '127.0.0.2')
console.log(cache.get('hello', 2)) // prints two of the above
// wait 2s
setTimeout(function () {
console.log(cache.get('hello', 2)) // prints []
}, 2000)
```
## API
#### `var cache = recordCache([options])`
Create a new record cache.
Options include:
``` js
{
maxSize: 1000, // approximate max size
maxAge: 1000, // approximate max age in ms
onStale: false // function called when evicting stale records
}
```
In the worst case the cache will be `2 * maxSize` large, and
if `maxAge` is used old values are gc'ed every `0.66 * maxAge - 1.33 * maxAge` with an optional callback to the `onStale` function upon record eviction.
This is to greatly simplify the data structures and also gives us a pretty decent
perf boost compared to other cache modules out there.
#### `cache.add(recordName, value)`
Push a new value to the record set. `value` should be serialisable.
#### `cache.remove(recordName, value)`
Remove a value from the record set. `value` should be a previously added value.
#### `var list = cache.get(recordName, [maxCount])`
Get a list of values from the record set. The list will be randomised.
Specify `maxCount` to only get this many values at max.
#### `cache.size`
Get the actual size of the cache.
#### `cache.clear()`
Clear all values from the cache.
#### `cache.destroy()`
Completely destroy the cache. Needed if you are using the `maxAge` option to
cancel the gc timer.
## License
MIT
+13
View File
@@ -0,0 +1,13 @@
var recordCache = require('./')
var rc = recordCache({
maxAge: 10,
maxSize: 100
})
rc.add('hello', 'world')
rc.add('hello', 'welt')
rc.add('hello', 'verden')
console.log(rc.get('hello', 2))
setTimeout(() => console.log(rc.get('hello', 2)), 200)
+170
View File
@@ -0,0 +1,170 @@
const b4a = require('b4a')
var EMPTY = []
module.exports = RecordCache
function RecordSet () {
this.list = []
this.map = new Map()
}
RecordSet.prototype.add = function (record, value) {
var k = toString(record)
var r = this.map.get(k)
if (r) return false
r = {index: this.list.length, record: value || record}
this.list.push(r)
this.map.set(k, r)
return true
}
RecordSet.prototype.remove = function (record) {
var k = toString(record)
var r = this.map.get(k)
if (!r) return false
swap(this.list, r.index, this.list.length - 1)
this.list.pop()
this.map.delete(k)
return true
}
function RecordStore () {
this.records = new Map()
this.size = 0
}
RecordStore.prototype.add = function (name, record, value) {
var r = this.records.get(name)
if (!r) {
r = new RecordSet()
this.records.set(name, r)
}
if (r.add(record, value)) {
this.size++
return true
}
return false
}
RecordStore.prototype.remove = function (name, record, value) {
var r = this.records.get(name)
if (!r) return false
if (r.remove(record, value)) {
this.size--
if (!r.map.size) this.records.delete(name)
return true
}
return false
}
RecordStore.prototype.get = function (name) {
var r = this.records.get(name)
return r ? r.list : EMPTY
}
function RecordCache (opts) {
if (!(this instanceof RecordCache)) return new RecordCache(opts)
if (!opts) opts = {}
this.maxSize = opts.maxSize || Infinity
this.maxAge = opts.maxAge || 0
this._onstale = opts.onStale || opts.onstale || null
this._fresh = new RecordStore()
this._stale = new RecordStore()
this._interval = null
this._gced = false
if (this.maxAge && this.maxAge < Infinity) {
// 2/3 gives us a span of 0.66-1.33 maxAge or avg maxAge
var tick = Math.ceil(2 / 3 * this.maxAge)
this._interval = setInterval(this._gcAuto.bind(this), tick)
if (this._interval.unref) this._interval.unref()
}
}
Object.defineProperty(RecordCache.prototype, 'size', {
get: function () {
return this._fresh.size + this._stale.size
}
})
RecordCache.prototype.add = function (name, record, value) {
this._stale.remove(name, record, value)
if (this._fresh.add(name, record, value) && this._fresh.size > this.maxSize) {
this._gc()
}
}
RecordCache.prototype.remove = function (name, record, value) {
this._fresh.remove(name, record, value)
this._stale.remove(name, record, value)
}
RecordCache.prototype.get = function (name, n) {
var a = this._fresh.get(name)
var b = this._stale.get(name)
var aLen = a.length
var bLen = b.length
var len = aLen + bLen
if (n > len || !n) n = len
var result = new Array(n)
for (var i = 0; i < n; i++) {
var j = Math.floor(Math.random() * (aLen + bLen))
if (j < aLen) {
result[i] = a[j].record
swap(a, j, --aLen)
} else {
j -= aLen
result[i] = b[j].record
swap(b, j, --bLen)
}
}
return result
}
RecordCache.prototype._gcAuto = function () {
if (!this._gced) this._gc()
this._gced = false
}
RecordCache.prototype._gc = function () {
if (this._onstale && this._stale.size > 0) this._onstale(this._stale)
this._stale = this._fresh
this._fresh = new RecordStore()
this._gced = true
}
RecordCache.prototype.clear = function () {
this._gc()
this._gc()
}
RecordCache.prototype.destroy = function () {
this.clear()
clearInterval(this._interval)
this._interval = null
}
function toString (record) {
return b4a.isBuffer(record) ? b4a.toString(record, 'hex') : record
}
function swap (list, a, b) {
var tmp = list[a]
tmp.index = b
list[b].index = a
list[a] = list[b]
list[b] = tmp
}
+26
View File
@@ -0,0 +1,26 @@
{
"name": "record-cache",
"version": "1.2.0",
"description": "Cache optimised for record like things",
"main": "index.js",
"dependencies": {
"b4a": "^1.3.1"
},
"devDependencies": {
"standard": "^10.0.3",
"tape": "^4.8.0"
},
"scripts": {
"test": "standard && tape test.js"
},
"repository": {
"type": "git",
"url": "https://github.com/mafintosh/record-cache.git"
},
"author": "Mathias Buus (@mafintosh)",
"license": "MIT",
"bugs": {
"url": "https://github.com/mafintosh/record-cache/issues"
},
"homepage": "https://github.com/mafintosh/record-cache"
}
+185
View File
@@ -0,0 +1,185 @@
var tape = require('tape')
var recordCache = require('./')
tape('add and get', function (t) {
var rc = recordCache()
rc.add('hello', 'world')
t.same(rc.get('hello'), ['world'])
t.end()
})
tape('add and get buffer', function (t) {
var rc = recordCache()
rc.add('hello', Buffer.from('world'))
t.same(rc.get('hello'), [Buffer.from('world')])
t.end()
})
tape('add and get (more than one)', function (t) {
var rc = recordCache()
rc.add('hello', 'world')
rc.add('hello', 'verden')
rc.add('hello', 'welt')
t.same(rc.get('hello').sort(), ['verden', 'welt', 'world'])
var list = rc.get('hello', 2)
t.ok(list[0] !== list[1])
t.ok(['verden', 'welt', 'world'].includes(list[0]))
t.ok(['verden', 'welt', 'world'].includes(list[1]))
t.end()
})
tape('get is randomised', function (t) {
var rc = recordCache()
rc.add('hello', 'a')
rc.add('hello', 'b')
rc.add('hello', 'c')
var map = {}
for (var i = 0; i < 1000; i++) {
map[rc.get('hello', 2).join('')] = true
}
t.same(map, {ab: true, ba: true, cb: true, bc: true, ac: true, ca: true})
t.end()
})
tape('get capped', function (t) {
var rc = recordCache({maxSize: 10})
for (var i = 0; i < 50; i++) {
rc.add('hello', '' + i)
}
t.ok(rc.get('hello').length <= 20)
t.ok(rc.size <= 20)
t.notOk(rc.get('hello').includes('0'))
t.notOk(rc.get('hello').includes('29'))
t.end()
})
tape('get capped with many record sets', function (t) {
var rc = recordCache({maxSize: 10})
for (var i = 0; i < 50; i++) {
rc.add('' + i, 'hello')
}
t.ok(rc.size <= 20)
t.same(rc.get('0'), [])
t.same(rc.get('29'), [])
t.same(rc.get('49'), ['hello'])
t.end()
})
tape('many updates is fine when capped', function (t) {
var rc = recordCache({maxSize: 10})
for (var i = 0; i < 10; i++) {
rc.add('hello', '' + i)
}
for (var j = 0; j < 100; j++) {
rc.add('hello', '9')
}
t.same(rc.get('hello').sort().join(''), '0123456789')
t.end()
})
tape('remove', function (t) {
var rc = recordCache()
t.same(rc.get('hello'), [])
rc.remove('hello', 'world')
t.same(rc.get('hello'), [])
rc.add('hello', 'world')
t.same(rc.get('hello'), ['world'])
rc.remove('hello', 'world')
t.same(rc.get('hello'), [])
t.end()
})
tape('remove with other value', function (t) {
var rc = recordCache()
rc.add('hello', 'hi')
t.same(rc.get('hello'), ['hi'])
rc.remove('hello', 'world')
t.same(rc.get('hello'), ['hi'])
rc.add('hello', 'world')
t.same(rc.get('hello').sort(), ['hi', 'world'])
rc.remove('hello', 'world')
t.same(rc.get('hello'), ['hi'])
t.end()
})
tape('clear', function (t) {
var rc = recordCache()
rc.clear()
t.same(rc.get('hello'), [])
rc.add('hello', 'a')
rc.add('hello', 'b')
rc.add('foo', 'bar')
t.same(rc.get('hello').sort(), ['a', 'b'])
rc.clear()
t.same(rc.get('hello'), [])
t.same(rc.get('foo'), [])
t.end()
})
tape('maxAge', function (t) {
var rc = recordCache({maxAge: 20})
rc.add('hello', 'world')
rc.add('hello', 'verden')
setTimeout(function () {
t.same(rc.get('hello').sort(), ['verden', 'world'])
setTimeout(function () {
t.same(rc.get('hello'), [])
rc.destroy()
t.end()
}, 35)
}, 5)
})
tape('maxAge but one value is staying alive', function (t) {
var rc = recordCache({maxAge: 20})
rc.add('hello', 'world')
rc.add('hello', 'verden')
var interval = setInterval(function () {
rc.add('hello', 'verden')
}, 5)
setTimeout(function () {
t.same(rc.get('hello').sort(), ['verden', 'world'])
setTimeout(function () {
clearInterval(interval)
t.same(rc.get('hello'), ['verden'])
rc.destroy()
t.end()
}, 35)
}, 5)
})
tape('add dedups buffers', function (t) {
var rc = recordCache()
rc.add('hello', Buffer.from('world'))
rc.add('hello', Buffer.from('world'))
t.same(rc.get('hello'), [Buffer.from('world')])
t.end()
})
tape('add and remove buffer', function (t) {
var rc = recordCache()
rc.add('hello', Buffer.from('world'))
rc.remove('hello', Buffer.from('world'))
t.same(rc.get('hello'), [])
t.end()
})