distillate 0.1.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/LICENSE +21 -0
- package/README.md +105 -0
- package/dist/blocked/index.cjs +116 -0
- package/dist/blocked/index.d.cts +29 -0
- package/dist/blocked/index.d.ts +29 -0
- package/dist/blocked/index.js +114 -0
- package/dist/bloom/index.cjs +132 -0
- package/dist/bloom/index.d.cts +24 -0
- package/dist/bloom/index.d.ts +24 -0
- package/dist/bloom/index.js +130 -0
- package/dist/bytes-DCuYtUVS.d.cts +4 -0
- package/dist/bytes-DCuYtUVS.d.ts +4 -0
- package/dist/fuse/index.cjs +298 -0
- package/dist/fuse/index.d.cts +35 -0
- package/dist/fuse/index.d.ts +35 -0
- package/dist/fuse/index.js +295 -0
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/serialize-C5rwVPvv.cjs +312 -0
- package/dist/serialize-E_4WyueA.js +271 -0
- package/package.json +114 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
//#region src/core/bytes.ts
|
|
2
|
+
const encoder = new TextEncoder();
|
|
3
|
+
function normalize(input) {
|
|
4
|
+
if (typeof input === "string") return encoder.encode(input);
|
|
5
|
+
if (input instanceof Uint8Array) return input;
|
|
6
|
+
return new Uint8Array(input);
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/core/hasher.ts
|
|
10
|
+
const C1LO = 289559509;
|
|
11
|
+
const C1HI = 2277735313;
|
|
12
|
+
const C2LO = 658871167;
|
|
13
|
+
const C2HI = 1291169091;
|
|
14
|
+
let RLO = 0;
|
|
15
|
+
let RHI = 0;
|
|
16
|
+
function mul64(alo, ahi, blo, bhi) {
|
|
17
|
+
const a0 = alo & 65535;
|
|
18
|
+
const a1 = alo >>> 16;
|
|
19
|
+
const a2 = ahi & 65535;
|
|
20
|
+
const a3 = ahi >>> 16;
|
|
21
|
+
const b0 = blo & 65535;
|
|
22
|
+
const b1 = blo >>> 16;
|
|
23
|
+
const b2 = bhi & 65535;
|
|
24
|
+
const b3 = bhi >>> 16;
|
|
25
|
+
let c0 = a0 * b0;
|
|
26
|
+
let c1 = c0 >>> 16;
|
|
27
|
+
c0 &= 65535;
|
|
28
|
+
c1 += a1 * b0;
|
|
29
|
+
let c2 = c1 >>> 16;
|
|
30
|
+
c1 &= 65535;
|
|
31
|
+
c1 += a0 * b1;
|
|
32
|
+
c2 += c1 >>> 16;
|
|
33
|
+
c1 &= 65535;
|
|
34
|
+
c2 += a2 * b0;
|
|
35
|
+
let c3 = c2 >>> 16;
|
|
36
|
+
c2 &= 65535;
|
|
37
|
+
c2 += a1 * b1;
|
|
38
|
+
c3 += c2 >>> 16;
|
|
39
|
+
c2 &= 65535;
|
|
40
|
+
c2 += a0 * b2;
|
|
41
|
+
c3 += c2 >>> 16;
|
|
42
|
+
c2 &= 65535;
|
|
43
|
+
c3 += a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3;
|
|
44
|
+
c3 &= 65535;
|
|
45
|
+
RLO = (c1 << 16 | c0) >>> 0;
|
|
46
|
+
RHI = (c3 << 16 | c2) >>> 0;
|
|
47
|
+
}
|
|
48
|
+
function rotl64(lo, hi, r) {
|
|
49
|
+
if (r < 32) {
|
|
50
|
+
RLO = (lo << r | hi >>> 32 - r) >>> 0;
|
|
51
|
+
RHI = (hi << r | lo >>> 32 - r) >>> 0;
|
|
52
|
+
} else {
|
|
53
|
+
const s = r - 32;
|
|
54
|
+
RLO = (hi << s | lo >>> 32 - s) >>> 0;
|
|
55
|
+
RHI = (lo << s | hi >>> 32 - s) >>> 0;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function add64(alo, ahi, blo, bhi) {
|
|
59
|
+
const lo = (alo >>> 0) + (blo >>> 0);
|
|
60
|
+
RHI = ahi + bhi + (lo > 4294967295 ? 1 : 0) >>> 0;
|
|
61
|
+
RLO = lo >>> 0;
|
|
62
|
+
}
|
|
63
|
+
function fmix64(lo, hi) {
|
|
64
|
+
let l = lo;
|
|
65
|
+
let h = hi;
|
|
66
|
+
l = (l ^ h >>> 1) >>> 0;
|
|
67
|
+
mul64(l, h, 3981806797, 4283543511);
|
|
68
|
+
l = RLO;
|
|
69
|
+
h = RHI;
|
|
70
|
+
l = (l ^ h >>> 1) >>> 0;
|
|
71
|
+
mul64(l, h, 444984403, 3301882366);
|
|
72
|
+
l = RLO;
|
|
73
|
+
h = RHI;
|
|
74
|
+
l = (l ^ h >>> 1) >>> 0;
|
|
75
|
+
RLO = l;
|
|
76
|
+
RHI = h;
|
|
77
|
+
}
|
|
78
|
+
function hash128(bytes, seed = 0) {
|
|
79
|
+
const len = bytes.length;
|
|
80
|
+
const nblocks = len >>> 4;
|
|
81
|
+
let h1lo = seed >>> 0;
|
|
82
|
+
let h1hi = 0;
|
|
83
|
+
let h2lo = seed >>> 0;
|
|
84
|
+
let h2hi = 0;
|
|
85
|
+
for (let i = 0; i < nblocks; i++) {
|
|
86
|
+
const b = i * 16;
|
|
87
|
+
let k1lo = ((bytes[b] ?? 0) | (bytes[b + 1] ?? 0) << 8 | (bytes[b + 2] ?? 0) << 16 | (bytes[b + 3] ?? 0) << 24) >>> 0;
|
|
88
|
+
let k1hi = ((bytes[b + 4] ?? 0) | (bytes[b + 5] ?? 0) << 8 | (bytes[b + 6] ?? 0) << 16 | (bytes[b + 7] ?? 0) << 24) >>> 0;
|
|
89
|
+
let k2lo = ((bytes[b + 8] ?? 0) | (bytes[b + 9] ?? 0) << 8 | (bytes[b + 10] ?? 0) << 16 | (bytes[b + 11] ?? 0) << 24) >>> 0;
|
|
90
|
+
let k2hi = ((bytes[b + 12] ?? 0) | (bytes[b + 13] ?? 0) << 8 | (bytes[b + 14] ?? 0) << 16 | (bytes[b + 15] ?? 0) << 24) >>> 0;
|
|
91
|
+
mul64(k1lo, k1hi, C1LO, C1HI);
|
|
92
|
+
rotl64(RLO, RHI, 31);
|
|
93
|
+
mul64(RLO, RHI, C2LO, C2HI);
|
|
94
|
+
k1lo = RLO;
|
|
95
|
+
k1hi = RHI;
|
|
96
|
+
h1lo ^= k1lo;
|
|
97
|
+
h1hi ^= k1hi;
|
|
98
|
+
rotl64(h1lo, h1hi, 27);
|
|
99
|
+
add64(RLO, RHI, h2lo, h2hi);
|
|
100
|
+
mul64(RLO, RHI, 5, 0);
|
|
101
|
+
add64(RLO, RHI, 1390208809, 0);
|
|
102
|
+
h1lo = RLO;
|
|
103
|
+
h1hi = RHI;
|
|
104
|
+
mul64(k2lo, k2hi, C2LO, C2HI);
|
|
105
|
+
rotl64(RLO, RHI, 33);
|
|
106
|
+
mul64(RLO, RHI, C1LO, C1HI);
|
|
107
|
+
k2lo = RLO;
|
|
108
|
+
k2hi = RHI;
|
|
109
|
+
h2lo ^= k2lo;
|
|
110
|
+
h2hi ^= k2hi;
|
|
111
|
+
rotl64(h2lo, h2hi, 31);
|
|
112
|
+
add64(RLO, RHI, h1lo, h1hi);
|
|
113
|
+
mul64(RLO, RHI, 5, 0);
|
|
114
|
+
add64(RLO, RHI, 944331445, 0);
|
|
115
|
+
h2lo = RLO;
|
|
116
|
+
h2hi = RHI;
|
|
117
|
+
}
|
|
118
|
+
let k1lo = 0;
|
|
119
|
+
let k1hi = 0;
|
|
120
|
+
let k2lo = 0;
|
|
121
|
+
let k2hi = 0;
|
|
122
|
+
const tail = nblocks * 16;
|
|
123
|
+
const rem = len & 15;
|
|
124
|
+
if (rem >= 15) k2hi ^= (bytes[tail + 14] ?? 0) << 16;
|
|
125
|
+
if (rem >= 14) k2hi ^= (bytes[tail + 13] ?? 0) << 8;
|
|
126
|
+
if (rem >= 13) k2hi ^= bytes[tail + 12] ?? 0;
|
|
127
|
+
if (rem >= 12) k2lo ^= (bytes[tail + 11] ?? 0) << 24;
|
|
128
|
+
if (rem >= 11) k2lo ^= (bytes[tail + 10] ?? 0) << 16;
|
|
129
|
+
if (rem >= 10) k2lo ^= (bytes[tail + 9] ?? 0) << 8;
|
|
130
|
+
if (rem >= 9) {
|
|
131
|
+
k2lo ^= bytes[tail + 8] ?? 0;
|
|
132
|
+
k2lo >>>= 0;
|
|
133
|
+
k2hi >>>= 0;
|
|
134
|
+
mul64(k2lo, k2hi, C2LO, C2HI);
|
|
135
|
+
rotl64(RLO, RHI, 33);
|
|
136
|
+
mul64(RLO, RHI, C1LO, C1HI);
|
|
137
|
+
h2lo ^= RLO;
|
|
138
|
+
h2hi ^= RHI;
|
|
139
|
+
}
|
|
140
|
+
if (rem >= 8) k1hi ^= (bytes[tail + 7] ?? 0) << 24;
|
|
141
|
+
if (rem >= 7) k1hi ^= (bytes[tail + 6] ?? 0) << 16;
|
|
142
|
+
if (rem >= 6) k1hi ^= (bytes[tail + 5] ?? 0) << 8;
|
|
143
|
+
if (rem >= 5) k1hi ^= bytes[tail + 4] ?? 0;
|
|
144
|
+
if (rem >= 4) k1lo ^= (bytes[tail + 3] ?? 0) << 24;
|
|
145
|
+
if (rem >= 3) k1lo ^= (bytes[tail + 2] ?? 0) << 16;
|
|
146
|
+
if (rem >= 2) k1lo ^= (bytes[tail + 1] ?? 0) << 8;
|
|
147
|
+
if (rem >= 1) {
|
|
148
|
+
k1lo ^= bytes[tail] ?? 0;
|
|
149
|
+
k1lo >>>= 0;
|
|
150
|
+
k1hi >>>= 0;
|
|
151
|
+
mul64(k1lo, k1hi, C1LO, C1HI);
|
|
152
|
+
rotl64(RLO, RHI, 31);
|
|
153
|
+
mul64(RLO, RHI, C2LO, C2HI);
|
|
154
|
+
h1lo ^= RLO;
|
|
155
|
+
h1hi ^= RHI;
|
|
156
|
+
}
|
|
157
|
+
h1lo = (h1lo ^ len) >>> 0;
|
|
158
|
+
h2lo = (h2lo ^ len) >>> 0;
|
|
159
|
+
add64(h1lo, h1hi, h2lo, h2hi);
|
|
160
|
+
h1lo = RLO;
|
|
161
|
+
h1hi = RHI;
|
|
162
|
+
add64(h2lo, h2hi, h1lo, h1hi);
|
|
163
|
+
h2lo = RLO;
|
|
164
|
+
h2hi = RHI;
|
|
165
|
+
fmix64(h1lo, h1hi);
|
|
166
|
+
h1lo = RLO;
|
|
167
|
+
h1hi = RHI;
|
|
168
|
+
fmix64(h2lo, h2hi);
|
|
169
|
+
h2lo = RLO;
|
|
170
|
+
h2hi = RHI;
|
|
171
|
+
add64(h1lo, h1hi, h2lo, h2hi);
|
|
172
|
+
h1lo = RLO;
|
|
173
|
+
h1hi = RHI;
|
|
174
|
+
add64(h2lo, h2hi, h1lo, h1hi);
|
|
175
|
+
h2lo = RLO;
|
|
176
|
+
h2hi = RHI;
|
|
177
|
+
return {
|
|
178
|
+
h1lo: h1lo >>> 0,
|
|
179
|
+
h1hi: h1hi >>> 0,
|
|
180
|
+
h2lo: h2lo >>> 0,
|
|
181
|
+
h2hi: h2hi >>> 0
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function reduce(x, range) {
|
|
185
|
+
const xlo = x & 65535;
|
|
186
|
+
const xhi = x >>> 16;
|
|
187
|
+
const rlo = range & 65535;
|
|
188
|
+
const rhi = range >>> 16;
|
|
189
|
+
const lolo = xlo * rlo;
|
|
190
|
+
const lohi = xlo * rhi;
|
|
191
|
+
const hilo = xhi * rlo;
|
|
192
|
+
const hihi = xhi * rhi;
|
|
193
|
+
const carry = (lolo >>> 16) + (lohi & 65535) + (hilo & 65535);
|
|
194
|
+
return hihi + (lohi >>> 16) + (hilo >>> 16) + (carry >>> 16) >>> 0;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Derive `count` bucket indices in `[0, range)` from a key using
|
|
198
|
+
* Kirsch-Mitzenmacher enhanced double hashing `g_i = h1 + i*h2 + i^2`
|
|
199
|
+
* (the RocksDB `+i^2` fix), reduced into range with Lemire multiply-shift.
|
|
200
|
+
*/
|
|
201
|
+
function probeInto(key, count, range, seed, out) {
|
|
202
|
+
const { h1lo, h1hi, h2lo, h2hi } = hash128(normalize(key), seed);
|
|
203
|
+
const a = (h1lo ^ h1hi) >>> 0;
|
|
204
|
+
const b = (h2lo ^ h2hi) >>> 0;
|
|
205
|
+
for (let i = 0; i < count; i++) out[i] = reduce(a + Math.imul(i, b) + i * i >>> 0, range);
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/core/crc32.ts
|
|
209
|
+
let table;
|
|
210
|
+
function buildTable() {
|
|
211
|
+
const t = /* @__PURE__ */ new Uint32Array(256);
|
|
212
|
+
for (let n = 0; n < 256; n++) {
|
|
213
|
+
let c = n;
|
|
214
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
215
|
+
t[n] = c >>> 0;
|
|
216
|
+
}
|
|
217
|
+
return t;
|
|
218
|
+
}
|
|
219
|
+
function crc32(bytes) {
|
|
220
|
+
table ??= buildTable();
|
|
221
|
+
let crc = 4294967295;
|
|
222
|
+
for (const byte of bytes) crc = (table[(crc ^ byte) & 255] ?? 0) ^ crc >>> 8;
|
|
223
|
+
return (crc ^ 4294967295) >>> 0;
|
|
224
|
+
}
|
|
225
|
+
const HEADER_SIZE = 8;
|
|
226
|
+
const TRAILER_SIZE = 4;
|
|
227
|
+
function writeHeader(header, body) {
|
|
228
|
+
const frame = new Uint8Array(HEADER_SIZE + body.length + TRAILER_SIZE);
|
|
229
|
+
frame[0] = 65;
|
|
230
|
+
frame[1] = 77;
|
|
231
|
+
frame[2] = 81;
|
|
232
|
+
frame[3] = 70;
|
|
233
|
+
frame[4] = header.version;
|
|
234
|
+
frame[5] = header.type;
|
|
235
|
+
frame[6] = header.flags;
|
|
236
|
+
frame[7] = 0;
|
|
237
|
+
frame.set(body, HEADER_SIZE);
|
|
238
|
+
const crc = crc32(frame.subarray(0, HEADER_SIZE + body.length));
|
|
239
|
+
new DataView(frame.buffer, frame.byteOffset, frame.byteLength).setUint32(HEADER_SIZE + body.length, crc, true);
|
|
240
|
+
return frame;
|
|
241
|
+
}
|
|
242
|
+
var SerializationError = class extends Error {
|
|
243
|
+
name = "SerializationError";
|
|
244
|
+
};
|
|
245
|
+
var TruncatedError = class extends SerializationError {
|
|
246
|
+
name = "TruncatedError";
|
|
247
|
+
};
|
|
248
|
+
var BadMagicError = class extends SerializationError {
|
|
249
|
+
name = "BadMagicError";
|
|
250
|
+
};
|
|
251
|
+
var UnknownVersionError = class extends SerializationError {
|
|
252
|
+
name = "UnknownVersionError";
|
|
253
|
+
};
|
|
254
|
+
var ChecksumError = class extends SerializationError {
|
|
255
|
+
name = "ChecksumError";
|
|
256
|
+
};
|
|
257
|
+
function readHeader(frame) {
|
|
258
|
+
if (frame.length < 12) throw new TruncatedError(`frame of ${String(frame.length)} bytes is shorter than the minimum ${String(12)}`);
|
|
259
|
+
if (frame[0] !== 65 || frame[1] !== 77 || frame[2] !== 81 || frame[3] !== 70) throw new BadMagicError("frame does not start with the AMQF magic");
|
|
260
|
+
const version = frame[4] ?? 0;
|
|
261
|
+
if (version !== 1) throw new UnknownVersionError(`unsupported format version ${String(version)}`);
|
|
262
|
+
if (new DataView(frame.buffer, frame.byteOffset, frame.byteLength).getUint32(frame.length - TRAILER_SIZE, true) !== crc32(frame.subarray(0, frame.length - TRAILER_SIZE))) throw new ChecksumError("frame CRC32 does not match its contents");
|
|
263
|
+
return {
|
|
264
|
+
version,
|
|
265
|
+
type: frame[5] ?? 0,
|
|
266
|
+
flags: frame[6] ?? 0,
|
|
267
|
+
body: frame.subarray(HEADER_SIZE, frame.length - TRAILER_SIZE)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
//#endregion
|
|
271
|
+
export { probeInto as a, hash128 as i, readHeader as n, reduce as o, writeHeader as r, normalize as s, SerializationError as t };
|
package/package.json
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "distillate",
|
|
3
|
+
"version": "0.1.0",
|
|
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
|
+
"keywords": [
|
|
6
|
+
"bloom-filter",
|
|
7
|
+
"cuckoo-filter",
|
|
8
|
+
"binary-fuse",
|
|
9
|
+
"xor-filter",
|
|
10
|
+
"amq",
|
|
11
|
+
"approximate-membership",
|
|
12
|
+
"probabilistic",
|
|
13
|
+
"probabilistic-data-structures",
|
|
14
|
+
"set",
|
|
15
|
+
"filter"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/akshay-xp/distillate.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/akshay-xp/distillate#readme",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": {
|
|
28
|
+
"import": "./dist/index.d.ts",
|
|
29
|
+
"require": "./dist/index.d.cts"
|
|
30
|
+
},
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"require": "./dist/index.cjs"
|
|
33
|
+
},
|
|
34
|
+
"./bloom": {
|
|
35
|
+
"types": {
|
|
36
|
+
"import": "./dist/bloom/index.d.ts",
|
|
37
|
+
"require": "./dist/bloom/index.d.cts"
|
|
38
|
+
},
|
|
39
|
+
"import": "./dist/bloom/index.js",
|
|
40
|
+
"require": "./dist/bloom/index.cjs"
|
|
41
|
+
},
|
|
42
|
+
"./blocked": {
|
|
43
|
+
"types": {
|
|
44
|
+
"import": "./dist/blocked/index.d.ts",
|
|
45
|
+
"require": "./dist/blocked/index.d.cts"
|
|
46
|
+
},
|
|
47
|
+
"import": "./dist/blocked/index.js",
|
|
48
|
+
"require": "./dist/blocked/index.cjs"
|
|
49
|
+
},
|
|
50
|
+
"./fuse": {
|
|
51
|
+
"types": {
|
|
52
|
+
"import": "./dist/fuse/index.d.ts",
|
|
53
|
+
"require": "./dist/fuse/index.d.cts"
|
|
54
|
+
},
|
|
55
|
+
"import": "./dist/fuse/index.js",
|
|
56
|
+
"require": "./dist/fuse/index.cjs"
|
|
57
|
+
},
|
|
58
|
+
"./package.json": "./package.json"
|
|
59
|
+
},
|
|
60
|
+
"main": "./dist/index.cjs",
|
|
61
|
+
"module": "./dist/index.js",
|
|
62
|
+
"types": "./dist/index.d.ts",
|
|
63
|
+
"files": [
|
|
64
|
+
"dist"
|
|
65
|
+
],
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsdown",
|
|
68
|
+
"publint": "publint --strict",
|
|
69
|
+
"check": "publint --strict && attw --pack . --profile node16",
|
|
70
|
+
"attw": "attw --pack . --profile node16",
|
|
71
|
+
"test": "vitest run",
|
|
72
|
+
"changeset": "changeset",
|
|
73
|
+
"version": "changeset version",
|
|
74
|
+
"release": "changeset publish",
|
|
75
|
+
"bench": "tsx bench/core.bench.ts && tsx bench/bloom.bench.ts && tsx bench/blocked.bench.ts && tsx bench/fuse.bench.ts",
|
|
76
|
+
"typecheck": "tsc --noEmit",
|
|
77
|
+
"format": "prettier --write .",
|
|
78
|
+
"format:check": "prettier --check .",
|
|
79
|
+
"lint": "eslint .",
|
|
80
|
+
"lint:fix": "eslint . --fix",
|
|
81
|
+
"prepare": "husky"
|
|
82
|
+
},
|
|
83
|
+
"lint-staged": {
|
|
84
|
+
"*.ts": [
|
|
85
|
+
"eslint --fix --no-warn-ignored",
|
|
86
|
+
"prettier --write"
|
|
87
|
+
],
|
|
88
|
+
"*.{js,mjs,cjs,json,md,yml,yaml}": "prettier --write"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
92
|
+
"@changesets/cli": "^2.31.1",
|
|
93
|
+
"@commitlint/cli": "^21.2.1",
|
|
94
|
+
"@commitlint/config-conventional": "^21.2.0",
|
|
95
|
+
"@eslint/js": "^10.0.1",
|
|
96
|
+
"eslint": "^10.8.0",
|
|
97
|
+
"eslint-config-prettier": "^10.1.8",
|
|
98
|
+
"fast-check": "^4.9.0",
|
|
99
|
+
"husky": "^9.1.7",
|
|
100
|
+
"lint-staged": "^17.2.0",
|
|
101
|
+
"mitata": "^1.0.34",
|
|
102
|
+
"prettier": "^3.9.6",
|
|
103
|
+
"publint": "^0.3.22",
|
|
104
|
+
"tsdown": "^0.22.14",
|
|
105
|
+
"tsx": "^4.23.1",
|
|
106
|
+
"typescript": "^5.9.3",
|
|
107
|
+
"typescript-eslint": "^8.65.0",
|
|
108
|
+
"vitest": "^4.1.10"
|
|
109
|
+
},
|
|
110
|
+
"engines": {
|
|
111
|
+
"node": ">=20"
|
|
112
|
+
},
|
|
113
|
+
"packageManager": "pnpm@10.33.0"
|
|
114
|
+
}
|