offheap 0.1.0 → 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/.github/workflows/CI.yml +22 -1
- package/Cargo.toml +2 -2
- package/artifacts/bindings-aarch64-apple-darwin/index.d.ts +37 -25
- package/artifacts/bindings-aarch64-apple-darwin/index.js +165 -295
- package/artifacts/bindings-aarch64-unknown-linux-musl/index.d.ts +42 -0
- package/artifacts/bindings-aarch64-unknown-linux-musl/index.js +186 -0
- package/artifacts/bindings-x86_64-apple-darwin/index.d.ts +37 -25
- package/artifacts/bindings-x86_64-apple-darwin/index.js +165 -295
- package/artifacts/bindings-x86_64-pc-windows-msvc/index.d.ts +42 -30
- package/artifacts/bindings-x86_64-pc-windows-msvc/index.js +186 -316
- package/artifacts/bindings-x86_64-unknown-linux-gnu/index.d.ts +37 -25
- package/artifacts/bindings-x86_64-unknown-linux-gnu/index.js +165 -295
- package/artifacts/bindings-x86_64-unknown-linux-musl/index.d.ts +42 -0
- package/artifacts/bindings-x86_64-unknown-linux-musl/index.js +186 -0
- package/benchmarks/crossover_bench.js +139 -0
- package/docs/.vitepress/config.js +35 -0
- package/docs/guide/api.md +216 -0
- package/docs/guide/architecture.md +58 -0
- package/docs/guide/benchmarks.md +48 -0
- package/docs/guide/getting-started.md +74 -0
- package/docs/index.md +23 -0
- package/index.d.ts +37 -25
- package/index.js +165 -295
- package/package.json +21 -12
- package/src/algorithms/arc.rs +123 -25
- package/src/algorithms/lru.rs +94 -12
- package/src/algorithms/mod.rs +4 -0
- package/src/algorithms/tinylfu.rs +98 -35
- package/src/cache.rs +289 -94
- package/tests/index.test.js +134 -7
package/index.js
CHANGED
|
@@ -1,316 +1,186 @@
|
|
|
1
|
-
|
|
2
|
-
/* eslint-disable */
|
|
3
|
-
/* prettier-ignore */
|
|
1
|
+
const { Cache: NativeCache, CacheManager: NativeCacheManager } = require('./binding');
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
const activePromises = new Map();
|
|
4
|
+
const finalizer = new FinalizationRegistry((nativeCache) => {
|
|
5
|
+
try {
|
|
6
|
+
nativeCache.dispose();
|
|
7
|
+
} catch (e) {
|
|
8
|
+
// Ignore errors during GC finalization
|
|
9
|
+
}
|
|
10
|
+
});
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
class Cache {
|
|
13
|
+
constructor(nativeCache) {
|
|
14
|
+
this._native = nativeCache;
|
|
15
|
+
this._id = Math.random().toString(36).substring(2);
|
|
16
|
+
finalizer.register(this, nativeCache, this);
|
|
17
|
+
}
|
|
9
18
|
|
|
10
|
-
|
|
19
|
+
get(key) {
|
|
20
|
+
return this._native.get(key);
|
|
21
|
+
}
|
|
11
22
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
peek(key) {
|
|
24
|
+
return this._native.peek(key);
|
|
25
|
+
}
|
|
15
26
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
-
try {
|
|
20
|
-
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
-
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
-
} catch (e) {
|
|
23
|
-
return true
|
|
24
|
-
}
|
|
25
|
-
} else {
|
|
26
|
-
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
-
return !glibcVersionRuntime
|
|
27
|
+
has(key) {
|
|
28
|
+
return this._native.has(key);
|
|
28
29
|
}
|
|
29
|
-
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
31
|
+
set(key, value, ttlMs) {
|
|
32
|
+
return this._native.set(key, value, ttlMs);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
touch(key, ttlMs) {
|
|
36
|
+
return this._native.touch(key, ttlMs);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
delete(key) {
|
|
40
|
+
return this._native.delete(key);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
clear() {
|
|
44
|
+
this._native.clear();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
stats() {
|
|
48
|
+
const rawStats = this._native.stats();
|
|
49
|
+
return {
|
|
50
|
+
hits: rawStats.hits,
|
|
51
|
+
misses: rawStats.misses,
|
|
52
|
+
capacity: rawStats.capacity,
|
|
53
|
+
size: rawStats.size,
|
|
54
|
+
bytesUsed: rawStats.bytesUsed,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
keys() {
|
|
59
|
+
return this._native.keys();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
increment(key, delta = 1, ttlMs) {
|
|
63
|
+
return this._native.increment(key, delta, ttlMs);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
decrement(key, delta = 1, ttlMs) {
|
|
67
|
+
return this._native.decrement(key, delta, ttlMs);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
mget(keys) {
|
|
71
|
+
return this._native.mget(keys);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
mset(entries, ttlMs) {
|
|
75
|
+
if (typeof entries !== 'object' || entries === null) {
|
|
76
|
+
throw new Error('mset requires an object of key-value entries');
|
|
60
77
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
try {
|
|
69
|
-
if (localFileExisted) {
|
|
70
|
-
nativeBinding = require('./offheap.win32-x64-msvc.node')
|
|
71
|
-
} else {
|
|
72
|
-
nativeBinding = require('offheap-win32-x64-msvc')
|
|
73
|
-
}
|
|
74
|
-
} catch (e) {
|
|
75
|
-
loadError = e
|
|
76
|
-
}
|
|
77
|
-
break
|
|
78
|
-
case 'ia32':
|
|
79
|
-
localFileExisted = existsSync(
|
|
80
|
-
join(__dirname, 'offheap.win32-ia32-msvc.node')
|
|
81
|
-
)
|
|
82
|
-
try {
|
|
83
|
-
if (localFileExisted) {
|
|
84
|
-
nativeBinding = require('./offheap.win32-ia32-msvc.node')
|
|
85
|
-
} else {
|
|
86
|
-
nativeBinding = require('offheap-win32-ia32-msvc')
|
|
87
|
-
}
|
|
88
|
-
} catch (e) {
|
|
89
|
-
loadError = e
|
|
90
|
-
}
|
|
91
|
-
break
|
|
92
|
-
case 'arm64':
|
|
93
|
-
localFileExisted = existsSync(
|
|
94
|
-
join(__dirname, 'offheap.win32-arm64-msvc.node')
|
|
95
|
-
)
|
|
96
|
-
try {
|
|
97
|
-
if (localFileExisted) {
|
|
98
|
-
nativeBinding = require('./offheap.win32-arm64-msvc.node')
|
|
99
|
-
} else {
|
|
100
|
-
nativeBinding = require('offheap-win32-arm64-msvc')
|
|
101
|
-
}
|
|
102
|
-
} catch (e) {
|
|
103
|
-
loadError = e
|
|
104
|
-
}
|
|
105
|
-
break
|
|
106
|
-
default:
|
|
107
|
-
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
78
|
+
this._native.mset(entries, ttlMs);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
mdelete(keys) {
|
|
82
|
+
if (!Array.isArray(keys)) {
|
|
83
|
+
throw new Error('mdelete requires an array of keys');
|
|
108
84
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
case 'x64':
|
|
122
|
-
localFileExisted = existsSync(join(__dirname, 'offheap.darwin-x64.node'))
|
|
123
|
-
try {
|
|
124
|
-
if (localFileExisted) {
|
|
125
|
-
nativeBinding = require('./offheap.darwin-x64.node')
|
|
126
|
-
} else {
|
|
127
|
-
nativeBinding = require('offheap-darwin-x64')
|
|
128
|
-
}
|
|
129
|
-
} catch (e) {
|
|
130
|
-
loadError = e
|
|
131
|
-
}
|
|
132
|
-
break
|
|
133
|
-
case 'arm64':
|
|
134
|
-
localFileExisted = existsSync(
|
|
135
|
-
join(__dirname, 'offheap.darwin-arm64.node')
|
|
136
|
-
)
|
|
137
|
-
try {
|
|
138
|
-
if (localFileExisted) {
|
|
139
|
-
nativeBinding = require('./offheap.darwin-arm64.node')
|
|
140
|
-
} else {
|
|
141
|
-
nativeBinding = require('offheap-darwin-arm64')
|
|
142
|
-
}
|
|
143
|
-
} catch (e) {
|
|
144
|
-
loadError = e
|
|
145
|
-
}
|
|
146
|
-
break
|
|
147
|
-
default:
|
|
148
|
-
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
85
|
+
return this._native.mdelete(keys);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
dispose() {
|
|
89
|
+
finalizer.unregister(this);
|
|
90
|
+
this._native.dispose();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getOrSet(key, factory, ttlMs) {
|
|
94
|
+
const val = this.get(key);
|
|
95
|
+
if (val !== undefined) {
|
|
96
|
+
return val;
|
|
149
97
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
|
|
98
|
+
|
|
99
|
+
const promiseKey = `${this._id}:${key}`;
|
|
100
|
+
if (activePromises.has(promiseKey)) {
|
|
101
|
+
return activePromises.get(promiseKey);
|
|
154
102
|
}
|
|
155
|
-
|
|
103
|
+
|
|
156
104
|
try {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
break
|
|
166
|
-
case 'linux':
|
|
167
|
-
switch (arch) {
|
|
168
|
-
case 'x64':
|
|
169
|
-
if (isMusl()) {
|
|
170
|
-
localFileExisted = existsSync(
|
|
171
|
-
join(__dirname, 'offheap.linux-x64-musl.node')
|
|
172
|
-
)
|
|
173
|
-
try {
|
|
174
|
-
if (localFileExisted) {
|
|
175
|
-
nativeBinding = require('./offheap.linux-x64-musl.node')
|
|
176
|
-
} else {
|
|
177
|
-
nativeBinding = require('offheap-linux-x64-musl')
|
|
178
|
-
}
|
|
179
|
-
} catch (e) {
|
|
180
|
-
loadError = e
|
|
181
|
-
}
|
|
182
|
-
} else {
|
|
183
|
-
localFileExisted = existsSync(
|
|
184
|
-
join(__dirname, 'offheap.linux-x64-gnu.node')
|
|
185
|
-
)
|
|
186
|
-
try {
|
|
187
|
-
if (localFileExisted) {
|
|
188
|
-
nativeBinding = require('./offheap.linux-x64-gnu.node')
|
|
189
|
-
} else {
|
|
190
|
-
nativeBinding = require('offheap-linux-x64-gnu')
|
|
191
|
-
}
|
|
192
|
-
} catch (e) {
|
|
193
|
-
loadError = e
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
break
|
|
197
|
-
case 'arm64':
|
|
198
|
-
if (isMusl()) {
|
|
199
|
-
localFileExisted = existsSync(
|
|
200
|
-
join(__dirname, 'offheap.linux-arm64-musl.node')
|
|
201
|
-
)
|
|
202
|
-
try {
|
|
203
|
-
if (localFileExisted) {
|
|
204
|
-
nativeBinding = require('./offheap.linux-arm64-musl.node')
|
|
205
|
-
} else {
|
|
206
|
-
nativeBinding = require('offheap-linux-arm64-musl')
|
|
207
|
-
}
|
|
208
|
-
} catch (e) {
|
|
209
|
-
loadError = e
|
|
210
|
-
}
|
|
211
|
-
} else {
|
|
212
|
-
localFileExisted = existsSync(
|
|
213
|
-
join(__dirname, 'offheap.linux-arm64-gnu.node')
|
|
214
|
-
)
|
|
215
|
-
try {
|
|
216
|
-
if (localFileExisted) {
|
|
217
|
-
nativeBinding = require('./offheap.linux-arm64-gnu.node')
|
|
218
|
-
} else {
|
|
219
|
-
nativeBinding = require('offheap-linux-arm64-gnu')
|
|
220
|
-
}
|
|
221
|
-
} catch (e) {
|
|
222
|
-
loadError = e
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
break
|
|
226
|
-
case 'arm':
|
|
227
|
-
if (isMusl()) {
|
|
228
|
-
localFileExisted = existsSync(
|
|
229
|
-
join(__dirname, 'offheap.linux-arm-musleabihf.node')
|
|
230
|
-
)
|
|
231
|
-
try {
|
|
232
|
-
if (localFileExisted) {
|
|
233
|
-
nativeBinding = require('./offheap.linux-arm-musleabihf.node')
|
|
234
|
-
} else {
|
|
235
|
-
nativeBinding = require('offheap-linux-arm-musleabihf')
|
|
236
|
-
}
|
|
237
|
-
} catch (e) {
|
|
238
|
-
loadError = e
|
|
239
|
-
}
|
|
240
|
-
} else {
|
|
241
|
-
localFileExisted = existsSync(
|
|
242
|
-
join(__dirname, 'offheap.linux-arm-gnueabihf.node')
|
|
243
|
-
)
|
|
244
|
-
try {
|
|
245
|
-
if (localFileExisted) {
|
|
246
|
-
nativeBinding = require('./offheap.linux-arm-gnueabihf.node')
|
|
247
|
-
} else {
|
|
248
|
-
nativeBinding = require('offheap-linux-arm-gnueabihf')
|
|
249
|
-
}
|
|
250
|
-
} catch (e) {
|
|
251
|
-
loadError = e
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
break
|
|
255
|
-
case 'riscv64':
|
|
256
|
-
if (isMusl()) {
|
|
257
|
-
localFileExisted = existsSync(
|
|
258
|
-
join(__dirname, 'offheap.linux-riscv64-musl.node')
|
|
259
|
-
)
|
|
260
|
-
try {
|
|
261
|
-
if (localFileExisted) {
|
|
262
|
-
nativeBinding = require('./offheap.linux-riscv64-musl.node')
|
|
263
|
-
} else {
|
|
264
|
-
nativeBinding = require('offheap-linux-riscv64-musl')
|
|
265
|
-
}
|
|
266
|
-
} catch (e) {
|
|
267
|
-
loadError = e
|
|
268
|
-
}
|
|
269
|
-
} else {
|
|
270
|
-
localFileExisted = existsSync(
|
|
271
|
-
join(__dirname, 'offheap.linux-riscv64-gnu.node')
|
|
272
|
-
)
|
|
273
|
-
try {
|
|
274
|
-
if (localFileExisted) {
|
|
275
|
-
nativeBinding = require('./offheap.linux-riscv64-gnu.node')
|
|
276
|
-
} else {
|
|
277
|
-
nativeBinding = require('offheap-linux-riscv64-gnu')
|
|
105
|
+
const res = factory();
|
|
106
|
+
if (res instanceof Promise) {
|
|
107
|
+
const p = res
|
|
108
|
+
.then((resolvedVal) => {
|
|
109
|
+
activePromises.delete(promiseKey);
|
|
110
|
+
if (resolvedVal !== undefined) {
|
|
111
|
+
this.set(key, resolvedVal, ttlMs);
|
|
278
112
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
nativeBinding = require('./offheap.linux-s390x-gnu.node')
|
|
291
|
-
} else {
|
|
292
|
-
nativeBinding = require('offheap-linux-s390x-gnu')
|
|
293
|
-
}
|
|
294
|
-
} catch (e) {
|
|
295
|
-
loadError = e
|
|
113
|
+
return resolvedVal;
|
|
114
|
+
})
|
|
115
|
+
.catch((err) => {
|
|
116
|
+
activePromises.delete(promiseKey);
|
|
117
|
+
throw err;
|
|
118
|
+
});
|
|
119
|
+
activePromises.set(promiseKey, p);
|
|
120
|
+
return p;
|
|
121
|
+
} else {
|
|
122
|
+
if (res !== undefined) {
|
|
123
|
+
this.set(key, res, ttlMs);
|
|
296
124
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
125
|
+
return res;
|
|
126
|
+
}
|
|
127
|
+
} catch (err) {
|
|
128
|
+
activePromises.delete(promiseKey);
|
|
129
|
+
throw err;
|
|
300
130
|
}
|
|
301
|
-
|
|
302
|
-
default:
|
|
303
|
-
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
131
|
+
}
|
|
304
132
|
}
|
|
305
133
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
134
|
+
const activeManagers = new Set();
|
|
135
|
+
|
|
136
|
+
class CacheManager {
|
|
137
|
+
constructor() {
|
|
138
|
+
this._native = new NativeCacheManager();
|
|
139
|
+
activeManagers.add(this);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
createCache(name, config) {
|
|
143
|
+
const rawConfig = {
|
|
144
|
+
policy: config.policy,
|
|
145
|
+
capacity: config.capacity,
|
|
146
|
+
shards: config.shards,
|
|
147
|
+
maxBytes: config.maxBytes,
|
|
148
|
+
};
|
|
149
|
+
const nativeCache = this._native.createCache(name, rawConfig);
|
|
150
|
+
return new Cache(nativeCache);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
getCache(name) {
|
|
154
|
+
const nativeCache = this._native.getCache(name);
|
|
155
|
+
if (!nativeCache) return null;
|
|
156
|
+
return new Cache(nativeCache);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
deleteCache(name) {
|
|
160
|
+
return this._native.deleteCache(name);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
clear() {
|
|
164
|
+
this._native.clear();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
dispose() {
|
|
168
|
+
activeManagers.delete(this);
|
|
169
|
+
this._native.clear();
|
|
309
170
|
}
|
|
310
|
-
throw new Error(`Failed to load native binding`)
|
|
311
171
|
}
|
|
312
172
|
|
|
313
|
-
|
|
173
|
+
process.on('exit', () => {
|
|
174
|
+
for (const manager of activeManagers) {
|
|
175
|
+
try {
|
|
176
|
+
manager.dispose();
|
|
177
|
+
} catch (e) {
|
|
178
|
+
// Ignore cleanup failures on process exit
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
314
182
|
|
|
315
|
-
module.exports
|
|
316
|
-
|
|
183
|
+
module.exports = {
|
|
184
|
+
Cache,
|
|
185
|
+
CacheManager,
|
|
186
|
+
};
|
package/package.json
CHANGED
|
@@ -1,35 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "offheap",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "High-performance off-heap caching framework for Node.js written in Rust",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"napi": {
|
|
8
8
|
"name": "offheap",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
9
|
+
"targets": [
|
|
10
|
+
"x86_64-pc-windows-msvc",
|
|
11
|
+
"x86_64-unknown-linux-gnu",
|
|
12
|
+
"x86_64-unknown-linux-musl",
|
|
13
|
+
"x86_64-apple-darwin",
|
|
14
|
+
"aarch64-apple-darwin",
|
|
15
|
+
"aarch64-unknown-linux-musl"
|
|
16
|
+
]
|
|
13
17
|
},
|
|
14
18
|
"scripts": {
|
|
15
19
|
"artifacts": "napi artifacts",
|
|
16
|
-
"build": "napi build --platform --release",
|
|
17
|
-
"build:debug": "napi build --platform",
|
|
20
|
+
"build": "napi build --platform --release --js binding.js --dts binding.d.ts",
|
|
21
|
+
"build:debug": "napi build --platform --js binding.js --dts binding.d.ts",
|
|
18
22
|
"prepublishOnly": "napi prepublish -t npm --skip-gh-release",
|
|
19
23
|
"test": "node --test tests/index.test.js",
|
|
20
|
-
"benchmark": "node benchmarks/js_bench.js"
|
|
24
|
+
"benchmark": "node benchmarks/js_bench.js",
|
|
25
|
+
"docs:dev": "vitepress dev docs",
|
|
26
|
+
"docs:build": "vitepress build docs",
|
|
27
|
+
"docs:preview": "vitepress preview docs"
|
|
21
28
|
},
|
|
22
29
|
"devDependencies": {
|
|
23
30
|
"@napi-rs/cli": "^2.18.4",
|
|
24
|
-
"
|
|
31
|
+
"lru-cache": "^11.5.2",
|
|
32
|
+
"tinybench": "^2.9.0",
|
|
33
|
+
"vitepress": "^1.0.2"
|
|
25
34
|
},
|
|
26
35
|
"engines": {
|
|
27
36
|
"node": ">= 18"
|
|
28
37
|
},
|
|
29
38
|
"license": "MIT OR Apache-2.0",
|
|
30
39
|
"optionalDependencies": {
|
|
31
|
-
"offheap-win32-x64-msvc": "0.
|
|
32
|
-
"offheap-darwin-x64": "0.
|
|
33
|
-
"offheap-linux-x64-gnu": "0.
|
|
40
|
+
"offheap-win32-x64-msvc": "0.2.0",
|
|
41
|
+
"offheap-darwin-x64": "0.2.0",
|
|
42
|
+
"offheap-linux-x64-gnu": "0.2.0"
|
|
34
43
|
}
|
|
35
44
|
}
|