distillate 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/blocked/index.cjs +62 -7
- package/dist/blocked/index.d.cts +60 -7
- package/dist/blocked/index.d.ts +60 -7
- package/dist/blocked/index.js +62 -8
- package/dist/bloom/index.cjs +61 -0
- package/dist/bloom/index.d.cts +60 -1
- package/dist/bloom/index.d.ts +60 -1
- package/dist/bloom/index.js +61 -1
- package/dist/fuse/index.cjs +66 -0
- package/dist/fuse/index.d.cts +66 -0
- package/dist/fuse/index.d.ts +66 -0
- package/dist/fuse/index.js +66 -0
- package/dist/index.cjs +3 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/params-ChTRNxM9.js +24 -0
- package/dist/params-DnqJBqLS.d.cts +8 -0
- package/dist/params-DnqJBqLS.d.ts +8 -0
- package/dist/params-J8p3bKq5.cjs +53 -0
- package/package.json +10 -1
package/dist/fuse/index.js
CHANGED
|
@@ -3,7 +3,9 @@ import { i as hash128KeyInto, n as readHeader, r as writeHeader, t as Serializat
|
|
|
3
3
|
const ARITY = 3;
|
|
4
4
|
const TYPE_FUSE8 = 3;
|
|
5
5
|
const TYPE_FUSE16 = 4;
|
|
6
|
+
/** Thrown when binary fuse construction fails to converge on the key set. */
|
|
6
7
|
var BinaryFuseBuildError = class extends Error {
|
|
8
|
+
/** Discriminates this error from other `Error`s. */
|
|
7
9
|
name = "BinaryFuseBuildError";
|
|
8
10
|
};
|
|
9
11
|
let RLO = 0;
|
|
@@ -230,6 +232,10 @@ function fuseStateFromBytes(bytes, expectedType) {
|
|
|
230
232
|
size
|
|
231
233
|
};
|
|
232
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Shared behavior for the static binary fuse filters: an immutable,
|
|
237
|
+
* space-efficient membership filter built once from a fixed key set.
|
|
238
|
+
*/
|
|
233
239
|
var BinaryFuse = class {
|
|
234
240
|
#fp;
|
|
235
241
|
#seed;
|
|
@@ -246,12 +252,19 @@ var BinaryFuse = class {
|
|
|
246
252
|
this.#segCountLen = state.params.segCountLen;
|
|
247
253
|
this.#size = state.size;
|
|
248
254
|
}
|
|
255
|
+
/** Number of distinct keys the filter was built from. */
|
|
249
256
|
get size() {
|
|
250
257
|
return this.#size;
|
|
251
258
|
}
|
|
259
|
+
/** Actual bits stored per key (`0` for an empty filter). */
|
|
252
260
|
get bitsPerKey() {
|
|
253
261
|
return this.#size === 0 ? 0 : this.#fp.byteLength * 8 / this.#size;
|
|
254
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Serializes the filter to a portable little-endian byte layout.
|
|
265
|
+
*
|
|
266
|
+
* @returns The serialized filter, readable by the matching `fromBytes`.
|
|
267
|
+
*/
|
|
255
268
|
toBytes() {
|
|
256
269
|
const laneBytes = new Uint8Array(this.#fp.buffer, this.#fp.byteOffset, this.#fp.byteLength);
|
|
257
270
|
const body = new Uint8Array(16 + laneBytes.length);
|
|
@@ -267,6 +280,12 @@ var BinaryFuse = class {
|
|
|
267
280
|
flags: 0
|
|
268
281
|
}, body);
|
|
269
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Tests whether a key is in the set.
|
|
285
|
+
*
|
|
286
|
+
* @param key - The key to test.
|
|
287
|
+
* @returns `true` if present (possibly a false positive); `false` guarantees absence.
|
|
288
|
+
*/
|
|
270
289
|
has(key) {
|
|
271
290
|
if (this.#fp.length === 0) return false;
|
|
272
291
|
hash128KeyInto(key, 0, scratchHash);
|
|
@@ -281,18 +300,65 @@ var BinaryFuse = class {
|
|
|
281
300
|
return ((mlo ^ mhi) & mask) === (((this.#fp[p0] ?? 0) ^ (this.#fp[p1] ?? 0) ^ (this.#fp[p2] ?? 0)) & mask);
|
|
282
301
|
}
|
|
283
302
|
};
|
|
303
|
+
/**
|
|
304
|
+
* A static 8-bit binary fuse filter: built once from a key set, then immutable.
|
|
305
|
+
* The most space-efficient option (~9 bits/key at ~0.39% false-positive rate).
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```ts
|
|
309
|
+
* const filter = BinaryFuse8.from(["alice", "bob", "carol"]);
|
|
310
|
+
* filter.has("alice"); // true
|
|
311
|
+
* filter.size; // 3
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
284
314
|
var BinaryFuse8 = class BinaryFuse8 extends BinaryFuse {
|
|
315
|
+
/**
|
|
316
|
+
* Builds a filter from the given keys; duplicates are ignored.
|
|
317
|
+
*
|
|
318
|
+
* @param keys - The complete set of keys to store.
|
|
319
|
+
* @returns A new immutable filter.
|
|
320
|
+
* @throws {@link BinaryFuseBuildError} if construction fails to converge.
|
|
321
|
+
*/
|
|
285
322
|
static from(keys) {
|
|
286
323
|
return new BinaryFuse8(buildState(keys, (n) => new Uint8Array(n)));
|
|
287
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Restores a filter from its {@link BinaryFuse8.toBytes} serialization.
|
|
327
|
+
*
|
|
328
|
+
* @param bytes - The serialized filter.
|
|
329
|
+
* @returns The reconstructed filter.
|
|
330
|
+
*/
|
|
288
331
|
static fromBytes(bytes) {
|
|
289
332
|
return new BinaryFuse8(fuseStateFromBytes(bytes, TYPE_FUSE8));
|
|
290
333
|
}
|
|
291
334
|
};
|
|
335
|
+
/**
|
|
336
|
+
* A static 16-bit binary fuse filter: like {@link BinaryFuse8} but twice the
|
|
337
|
+
* space (~18 bits/key) for a far lower false-positive rate (~1/65536).
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```ts
|
|
341
|
+
* const filter = BinaryFuse16.from(["alice", "bob", "carol"]);
|
|
342
|
+
* filter.has("alice"); // true
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
292
345
|
var BinaryFuse16 = class BinaryFuse16 extends BinaryFuse {
|
|
346
|
+
/**
|
|
347
|
+
* Builds a filter from the given keys; duplicates are ignored.
|
|
348
|
+
*
|
|
349
|
+
* @param keys - The complete set of keys to store.
|
|
350
|
+
* @returns A new immutable filter.
|
|
351
|
+
* @throws {@link BinaryFuseBuildError} if construction fails to converge.
|
|
352
|
+
*/
|
|
293
353
|
static from(keys) {
|
|
294
354
|
return new BinaryFuse16(buildState(keys, (n) => new Uint16Array(n)));
|
|
295
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Restores a filter from its {@link BinaryFuse16.toBytes} serialization.
|
|
358
|
+
*
|
|
359
|
+
* @param bytes - The serialized filter.
|
|
360
|
+
* @returns The reconstructed filter.
|
|
361
|
+
*/
|
|
296
362
|
static fromBytes(bytes) {
|
|
297
363
|
return new BinaryFuse16(fuseStateFromBytes(bytes, TYPE_FUSE16));
|
|
298
364
|
}
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/core/params.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
var ParamError = class extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
name = "ParamError";
|
|
6
|
+
};
|
|
7
|
+
/** Asserts `value` is an integer greater than or equal to 1. */
|
|
8
|
+
function assertPositiveInt(value, label) {
|
|
9
|
+
if (!Number.isInteger(value) || value < 1) throw new ParamError(`${label} must be a positive integer, got ${String(value)}`);
|
|
10
|
+
}
|
|
11
|
+
/** Asserts `value` is a finite number greater than 0 (a positive real). */
|
|
12
|
+
function assertPositiveFinite(value, label) {
|
|
13
|
+
if (!Number.isFinite(value) || value <= 0) throw new ParamError(`${label} must be a positive number, got ${String(value)}`);
|
|
14
|
+
}
|
|
15
|
+
/** Asserts `value` is an integer in the uint32 range `[0, 2^32 - 1]`. */
|
|
16
|
+
function assertUint32(value, label) {
|
|
17
|
+
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new ParamError(`${label} must be a uint32, got ${String(value)}`);
|
|
18
|
+
}
|
|
19
|
+
/** Asserts `value` is a finite number in the open interval `(0, 1)`. */
|
|
20
|
+
function assertProbability(value, label) {
|
|
21
|
+
if (!Number.isFinite(value) || value <= 0 || value >= 1) throw new ParamError(`${label} must be in the open interval (0, 1), got ${String(value)}`);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { assertUint32 as a, assertProbability as i, assertPositiveFinite as n, assertPositiveInt as r, ParamError as t };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/core/params.d.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
declare class ParamError extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
override readonly name = "ParamError";
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { ParamError as t };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/core/params.d.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
declare class ParamError extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
override readonly name = "ParamError";
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { ParamError as t };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/core/params.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
var ParamError = class extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
name = "ParamError";
|
|
6
|
+
};
|
|
7
|
+
/** Asserts `value` is an integer greater than or equal to 1. */
|
|
8
|
+
function assertPositiveInt(value, label) {
|
|
9
|
+
if (!Number.isInteger(value) || value < 1) throw new ParamError(`${label} must be a positive integer, got ${String(value)}`);
|
|
10
|
+
}
|
|
11
|
+
/** Asserts `value` is a finite number greater than 0 (a positive real). */
|
|
12
|
+
function assertPositiveFinite(value, label) {
|
|
13
|
+
if (!Number.isFinite(value) || value <= 0) throw new ParamError(`${label} must be a positive number, got ${String(value)}`);
|
|
14
|
+
}
|
|
15
|
+
/** Asserts `value` is an integer in the uint32 range `[0, 2^32 - 1]`. */
|
|
16
|
+
function assertUint32(value, label) {
|
|
17
|
+
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new ParamError(`${label} must be a uint32, got ${String(value)}`);
|
|
18
|
+
}
|
|
19
|
+
/** Asserts `value` is a finite number in the open interval `(0, 1)`. */
|
|
20
|
+
function assertProbability(value, label) {
|
|
21
|
+
if (!Number.isFinite(value) || value <= 0 || value >= 1) throw new ParamError(`${label} must be in the open interval (0, 1), got ${String(value)}`);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
Object.defineProperty(exports, "ParamError", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function() {
|
|
27
|
+
return ParamError;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "assertPositiveFinite", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function() {
|
|
33
|
+
return assertPositiveFinite;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "assertPositiveInt", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function() {
|
|
39
|
+
return assertPositiveInt;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(exports, "assertProbability", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function() {
|
|
45
|
+
return assertProbability;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "assertUint32", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function() {
|
|
51
|
+
return assertUint32;
|
|
52
|
+
}
|
|
53
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "distillate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Probabilistic data structures for JavaScript. Space-efficient, approximate-membership filters (Bloom, Blocked Bloom, Binary Fuse) with tunable error and a portable binary format; zero dependencies, universal.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bloom-filter",
|
|
@@ -76,9 +76,12 @@
|
|
|
76
76
|
"@commitlint/cli": "^21.2.1",
|
|
77
77
|
"@commitlint/config-conventional": "^21.2.0",
|
|
78
78
|
"@eslint/js": "^10.0.1",
|
|
79
|
+
"@microsoft/api-extractor": "^7.58.12",
|
|
79
80
|
"@types/node": "^26.1.2",
|
|
81
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
80
82
|
"eslint": "^10.8.0",
|
|
81
83
|
"eslint-config-prettier": "^10.1.8",
|
|
84
|
+
"eslint-plugin-tsdoc": "^0.5.2",
|
|
82
85
|
"fast-check": "^4.9.0",
|
|
83
86
|
"husky": "^9.1.7",
|
|
84
87
|
"lint-staged": "^17.2.0",
|
|
@@ -87,6 +90,8 @@
|
|
|
87
90
|
"publint": "^0.3.22",
|
|
88
91
|
"tsdown": "^0.22.14",
|
|
89
92
|
"tsx": "^4.23.1",
|
|
93
|
+
"typedoc": "^0.28.20",
|
|
94
|
+
"typedoc-plugin-markdown": "^4.12.0",
|
|
90
95
|
"typescript": "^5.9.3",
|
|
91
96
|
"typescript-eslint": "^8.65.0",
|
|
92
97
|
"vitest": "^4.1.10"
|
|
@@ -100,6 +105,10 @@
|
|
|
100
105
|
"check": "publint --strict && attw --pack . --profile node16",
|
|
101
106
|
"attw": "attw --pack . --profile node16",
|
|
102
107
|
"test": "vitest run",
|
|
108
|
+
"coverage": "vitest run --coverage",
|
|
109
|
+
"api:report": "node scripts/api-extractor.mjs --local",
|
|
110
|
+
"api:check": "node scripts/api-extractor.mjs",
|
|
111
|
+
"docs:api": "typedoc",
|
|
103
112
|
"changeset": "changeset",
|
|
104
113
|
"version": "changeset version",
|
|
105
114
|
"release": "changeset publish",
|