mdbxmou 0.2.2 → 0.2.4
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 +36 -16
- package/build.js +15 -7
- package/lib/async.mjs +7 -0
- package/lib/index.mjs +12 -0
- package/lib/mdbx_worker.js +24 -8
- package/package.json +14 -1
package/README.md
CHANGED
|
@@ -19,6 +19,8 @@ npm install mdbxmou
|
|
|
19
19
|
|
|
20
20
|
## Quick Start
|
|
21
21
|
|
|
22
|
+
CommonJS:
|
|
23
|
+
|
|
22
24
|
```javascript
|
|
23
25
|
const { MDBX_Env, MDBX_Param } = require('mdbxmou');
|
|
24
26
|
|
|
@@ -47,6 +49,12 @@ readTxn.commit();
|
|
|
47
49
|
await env.close();
|
|
48
50
|
```
|
|
49
51
|
|
|
52
|
+
ESM:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
import { MDBX_Env, MDBX_Param } from "mdbxmou";
|
|
56
|
+
```
|
|
57
|
+
|
|
50
58
|
## API Reference
|
|
51
59
|
|
|
52
60
|
### Environment (MDBX_Env)
|
|
@@ -64,19 +72,19 @@ await env.open({
|
|
|
64
72
|
path: './database', // Database directory
|
|
65
73
|
keyFlag: MDBX_Param.keyFlag.string, // Default key encoding (optional)
|
|
66
74
|
valueFlag: MDBX_Param.valueFlag.string, // Default value encoding (optional)
|
|
67
|
-
|
|
75
|
+
flags: MDBX_Param.envFlag.nostickythreads
|
|
68
76
|
});
|
|
69
77
|
```
|
|
70
78
|
|
|
71
79
|
Options:
|
|
72
80
|
- `path` - Database directory path
|
|
81
|
+
- `flags` - Environment flags (optional, defaults to `0`)
|
|
73
82
|
- `keyFlag` - Default key encoding for all operations (optional, defaults to Buffer)
|
|
74
83
|
- Only `string` can be set (ordinal mode uses `number`/`bigint` separately)
|
|
75
84
|
- `valueFlag` - Default value encoding for all operations (optional, defaults to Buffer)
|
|
76
|
-
- `
|
|
77
|
-
- `
|
|
78
|
-
- `
|
|
79
|
-
- `maxDbs` - Maximum number of databases
|
|
85
|
+
- `maxDbi` - Maximum number of databases (optional, default `32`)
|
|
86
|
+
- `mode` - Filesystem permissions mode (optional, default `0664`)
|
|
87
|
+
- `geometry` - Map size/geometry options (optional)
|
|
80
88
|
|
|
81
89
|
Note: When `keyFlag` or `valueFlag` are set at environment level, they become defaults for all subsequent operations unless explicitly overridden.
|
|
82
90
|
|
|
@@ -124,14 +132,14 @@ const result = await env.query([
|
|
|
124
132
|
|
|
125
133
|
#### Methods
|
|
126
134
|
|
|
127
|
-
**createMap(keyMode, [valueMode], [
|
|
135
|
+
**createMap(db_name | keyMode, [keyMode | valueMode], [valueMode]) → DBI**
|
|
128
136
|
```javascript
|
|
129
|
-
// No arguments - default keyMode (0) and valueMode (0)
|
|
130
|
-
const dbi = txn.createMap();
|
|
131
|
-
|
|
132
137
|
// One argument - keyMode only
|
|
133
138
|
const dbi = txn.createMap(MDBX_Param.keyMode.ordinal);
|
|
134
139
|
|
|
140
|
+
// One argument - db_name only (uses default keyMode)
|
|
141
|
+
const namedDbi = txn.createMap("my-table");
|
|
142
|
+
|
|
135
143
|
// Two arguments - keyMode + valueMode
|
|
136
144
|
const dbi = txn.createMap(MDBX_Param.keyMode.ordinal, MDBX_Param.valueMode.multi);
|
|
137
145
|
|
|
@@ -144,17 +152,17 @@ const namedDbi = txn.createMap("my-table", MDBX_Param.keyMode.ordinal, MDBX_Para
|
|
|
144
152
|
|
|
145
153
|
> **Note**: Use `createMap` in write transactions - it will create the database if it doesn't exist, or open it if it does. This is safer for new environments.
|
|
146
154
|
|
|
147
|
-
**openMap(keyMode, [
|
|
155
|
+
**openMap(db_name | keyMode, [keyMode]) → DBI**
|
|
148
156
|
```javascript
|
|
149
|
-
// No arguments - default keyMode (0)
|
|
150
|
-
const dbi = txn.openMap();
|
|
151
|
-
|
|
152
157
|
// One argument - keyMode only
|
|
153
158
|
// Number keyMode - keys returned as numbers
|
|
154
159
|
const dbi = txn.openMap(MDBX_Param.keyMode.ordinal);
|
|
155
160
|
// BigInt keyMode - keys returned as BigInts
|
|
156
161
|
const dbi = txn.openMap(BigInt(MDBX_Param.keyMode.ordinal));
|
|
157
162
|
|
|
163
|
+
// One argument - db_name only (uses default keyMode)
|
|
164
|
+
const namedDbi = txn.openMap("my-table");
|
|
165
|
+
|
|
158
166
|
// Two arguments - db_name + keyMode
|
|
159
167
|
const namedDbi = txn.openMap("my-table", MDBX_Param.keyMode.ordinal);
|
|
160
168
|
const namedDbiBigInt = txn.openMap("my-table", BigInt(MDBX_Param.keyMode.ordinal));
|
|
@@ -536,7 +544,7 @@ try {
|
|
|
536
544
|
const dbi = txn.createMap(MDBX_Param.keyMode.ordinal);
|
|
537
545
|
|
|
538
546
|
// This might throw if key already exists with MDBX_NOOVERWRITE
|
|
539
|
-
dbi.put(txn, 123, "value"
|
|
547
|
+
dbi.put(txn, 123, "value");
|
|
540
548
|
|
|
541
549
|
txn.commit();
|
|
542
550
|
} catch (error) {
|
|
@@ -568,7 +576,17 @@ Note: For ordinal (integer) keys, use keyFlag.number or keyFlag.bigint to specif
|
|
|
568
576
|
|
|
569
577
|
### Environment Flags
|
|
570
578
|
- `MDBX_Param.envFlag.nostickythreads` - Don't stick reader transactions to threads
|
|
571
|
-
- `MDBX_Param.envFlag.
|
|
579
|
+
- `MDBX_Param.envFlag.rdonly` - Open database in read-only mode
|
|
580
|
+
- `MDBX_Param.envFlag.validation` - Enable page validation
|
|
581
|
+
- `MDBX_Param.envFlag.exclusive` - Exclusive mode
|
|
582
|
+
- `MDBX_Param.envFlag.accede` - Open existing environment
|
|
583
|
+
- `MDBX_Param.envFlag.writemap` - Use writable memory map
|
|
584
|
+
- `MDBX_Param.envFlag.nordahead` - Disable OS readahead
|
|
585
|
+
- `MDBX_Param.envFlag.nomeminit` - Disable memory initialization
|
|
586
|
+
- `MDBX_Param.envFlag.liforeclaim` - LIFO reclaim
|
|
587
|
+
- `MDBX_Param.envFlag.nometasync` - Disable metadata flushes
|
|
588
|
+
- `MDBX_Param.envFlag.safeNosync` - Safe nosync mode
|
|
589
|
+
- `MDBX_Param.envFlag.utterlyNosync` - Utterly nosync mode
|
|
572
590
|
|
|
573
591
|
### Database Modes
|
|
574
592
|
- `MDBX_Param.dbMode.create` - Create database if it doesn't exist
|
|
@@ -576,7 +594,9 @@ Note: For ordinal (integer) keys, use keyFlag.number or keyFlag.bigint to specif
|
|
|
576
594
|
|
|
577
595
|
### Query Modes
|
|
578
596
|
- `MDBX_Param.queryMode.get` - Read operations
|
|
579
|
-
- `MDBX_Param.queryMode.
|
|
597
|
+
- `MDBX_Param.queryMode.upsert` - Write operations (insert or update)
|
|
598
|
+
- `MDBX_Param.queryMode.update` - Update existing (MDBX_CURRENT)
|
|
599
|
+
- `MDBX_Param.queryMode.insertUnique` - Insert unique (MDBX_NOOVERWRITE)
|
|
580
600
|
- `MDBX_Param.queryMode.del` - Delete operations
|
|
581
601
|
|
|
582
602
|
### Cursor Modes
|
package/build.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
var spawnSync = require('child_process').spawnSync;
|
|
3
3
|
var fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
4
5
|
|
|
5
6
|
function exec(cmd) {
|
|
6
7
|
const { status } = spawnSync(cmd, {
|
|
@@ -14,6 +15,7 @@ function exec(cmd) {
|
|
|
14
15
|
|
|
15
16
|
// Create VERSION.json for libmdbx (needed for npm package)
|
|
16
17
|
const versionFile = 'deps/libmdbx/VERSION.json';
|
|
18
|
+
const libmdbxGitMarker = 'deps/libmdbx/.git';
|
|
17
19
|
if (!fs.existsSync(versionFile)) {
|
|
18
20
|
console.log('Creating VERSION.json for libmdbx...');
|
|
19
21
|
const versionJson = {
|
|
@@ -27,14 +29,20 @@ if (!fs.existsSync(versionFile)) {
|
|
|
27
29
|
console.log('VERSION.json created successfully!');
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
//
|
|
32
|
+
// Workaround for npm package: npm does not ship git metadata, while libmdbx
|
|
33
|
+
// may rely on it to determine version info during CMake configure.
|
|
34
|
+
// Apply this patch only when git metadata is missing.
|
|
31
35
|
const cmakeFile = 'deps/libmdbx/CMakeLists.txt';
|
|
32
|
-
if (fs.existsSync(cmakeFile)) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
if (!fs.existsSync(libmdbxGitMarker) && fs.existsSync(cmakeFile)) {
|
|
37
|
+
const cmakeText = fs.readFileSync(cmakeFile, 'utf8');
|
|
38
|
+
const from = 'if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git"';
|
|
39
|
+
const to = 'if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git"';
|
|
40
|
+
if (cmakeText.includes(from)) {
|
|
41
|
+
const patched = cmakeText.replace(from, to);
|
|
42
|
+
if (patched !== cmakeText) {
|
|
43
|
+
fs.writeFileSync(cmakeFile, patched);
|
|
44
|
+
console.log('Patched libmdbx CMakeLists.txt for npm package (no .git).');
|
|
45
|
+
}
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
|
package/lib/async.mjs
ADDED
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
const native = require("./nativemou.js");
|
|
6
|
+
const { MDBX_Async_Env } = require("./mdbx_evn_async.js");
|
|
7
|
+
|
|
8
|
+
export const MDBX_Env = native.MDBX_Env;
|
|
9
|
+
export const MDBX_Param = native.MDBX_Param;
|
|
10
|
+
export { MDBX_Async_Env };
|
|
11
|
+
|
|
12
|
+
export default native;
|
package/lib/mdbx_worker.js
CHANGED
|
@@ -82,17 +82,21 @@ async function handler(msg) {
|
|
|
82
82
|
|
|
83
83
|
case "dbi_put": {
|
|
84
84
|
const { txnId, dbiId, key, value, flags = 0 } = params;
|
|
85
|
+
const t = txns.get(txnId);
|
|
86
|
+
if (!t) throw new Error("no txn");
|
|
85
87
|
const d = dbis.get(dbiId);
|
|
86
88
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
87
|
-
d.dbi.put(key, value, flags);
|
|
89
|
+
d.dbi.put(t.txn, key, value, flags);
|
|
88
90
|
return ok(id, true);
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
case "dbi_get": {
|
|
92
94
|
const { txnId, dbiId, key } = params;
|
|
95
|
+
const t = txns.get(txnId);
|
|
96
|
+
if (!t) throw new Error("no txn");
|
|
93
97
|
const d = dbis.get(dbiId);
|
|
94
98
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
95
|
-
const val = d.dbi.get(key);
|
|
99
|
+
const val = d.dbi.get(t.txn, key);
|
|
96
100
|
// Если val это Buffer, преобразуем в строку для удобства
|
|
97
101
|
const result = (val && Buffer.isBuffer(val)) ? val.toString() : val;
|
|
98
102
|
return ok(id, result);
|
|
@@ -100,25 +104,31 @@ async function handler(msg) {
|
|
|
100
104
|
|
|
101
105
|
case "dbi_del": {
|
|
102
106
|
const { txnId, dbiId, key } = params;
|
|
107
|
+
const t = txns.get(txnId);
|
|
108
|
+
if (!t) throw new Error("no txn");
|
|
103
109
|
const d = dbis.get(dbiId);
|
|
104
110
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
105
|
-
const r = d.dbi.del(key);
|
|
111
|
+
const r = d.dbi.del(t.txn, key);
|
|
106
112
|
return ok(id, r);
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
case "dbi_stat": {
|
|
110
116
|
const { txnId, dbiId } = params;
|
|
117
|
+
const t = txns.get(txnId);
|
|
118
|
+
if (!t) throw new Error("no txn");
|
|
111
119
|
const d = dbis.get(dbiId);
|
|
112
120
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
113
|
-
return ok(id, d.dbi.stat());
|
|
121
|
+
return ok(id, d.dbi.stat(t.txn));
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
case "dbi_iter_all": {
|
|
117
125
|
const { txnId, dbiId } = params;
|
|
126
|
+
const t = txns.get(txnId);
|
|
127
|
+
if (!t) throw new Error("no txn");
|
|
118
128
|
const d = dbis.get(dbiId);
|
|
119
129
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
120
130
|
const out = [];
|
|
121
|
-
d.dbi.forEach((k, v) => {
|
|
131
|
+
d.dbi.forEach(t.txn, (k, v) => {
|
|
122
132
|
out.push({ key: k, value: v });
|
|
123
133
|
return true;
|
|
124
134
|
});
|
|
@@ -128,13 +138,15 @@ async function handler(msg) {
|
|
|
128
138
|
case "dbi_get_batch": {
|
|
129
139
|
// Групповое чтение множества ключей
|
|
130
140
|
const { txnId, dbiId, keys } = params;
|
|
141
|
+
const t = txns.get(txnId);
|
|
142
|
+
if (!t) throw new Error("no txn");
|
|
131
143
|
const d = dbis.get(dbiId);
|
|
132
144
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
133
145
|
|
|
134
146
|
const results = [];
|
|
135
147
|
for (const key of keys) {
|
|
136
148
|
try {
|
|
137
|
-
const val = d.dbi.get(key);
|
|
149
|
+
const val = d.dbi.get(t.txn, key);
|
|
138
150
|
if (val !== undefined && val !== null) {
|
|
139
151
|
const result = (val && Buffer.isBuffer(val)) ? val.toString() : val;
|
|
140
152
|
results.push({ key, value: result, found: true });
|
|
@@ -151,13 +163,15 @@ async function handler(msg) {
|
|
|
151
163
|
case "dbi_put_batch": {
|
|
152
164
|
// Групповая запись множества пар ключ-значение
|
|
153
165
|
const { txnId, dbiId, items, flags = 0 } = params;
|
|
166
|
+
const t = txns.get(txnId);
|
|
167
|
+
if (!t) throw new Error("no txn");
|
|
154
168
|
const d = dbis.get(dbiId);
|
|
155
169
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
156
170
|
|
|
157
171
|
const results = [];
|
|
158
172
|
for (const item of items) {
|
|
159
173
|
try {
|
|
160
|
-
d.dbi.put(item.key, item.value, flags);
|
|
174
|
+
d.dbi.put(t.txn, item.key, item.value, flags);
|
|
161
175
|
results.push({ key: item.key, success: true });
|
|
162
176
|
} catch (e) {
|
|
163
177
|
results.push({ key: item.key, success: false, error: e.message });
|
|
@@ -169,13 +183,15 @@ async function handler(msg) {
|
|
|
169
183
|
case "dbi_del_batch": {
|
|
170
184
|
// Групповое удаление множества ключей
|
|
171
185
|
const { txnId, dbiId, keys } = params;
|
|
186
|
+
const t = txns.get(txnId);
|
|
187
|
+
if (!t) throw new Error("no txn");
|
|
172
188
|
const d = dbis.get(dbiId);
|
|
173
189
|
if (!d || d.txnId !== txnId) throw new Error("no dbi");
|
|
174
190
|
|
|
175
191
|
const results = [];
|
|
176
192
|
for (const key of keys) {
|
|
177
193
|
try {
|
|
178
|
-
const r = d.dbi.del(key);
|
|
194
|
+
const r = d.dbi.del(t.txn, key);
|
|
179
195
|
results.push({ key, deleted: r });
|
|
180
196
|
} catch (e) {
|
|
181
197
|
results.push({ key, deleted: false, error: e.message });
|
package/package.json
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"main": "lib/nativemou.js",
|
|
3
|
+
"exports": {
|
|
4
|
+
".": {
|
|
5
|
+
"import": "./lib/index.mjs",
|
|
6
|
+
"require": "./lib/nativemou.js"
|
|
7
|
+
},
|
|
8
|
+
"./async": {
|
|
9
|
+
"import": "./lib/async.mjs",
|
|
10
|
+
"require": "./lib/mdbx_evn_async.js"
|
|
11
|
+
},
|
|
12
|
+
"./nativemou": "./lib/nativemou.js",
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
3
15
|
"files": [
|
|
4
16
|
"lib/**/*",
|
|
5
17
|
"src/**/*",
|
|
@@ -18,6 +30,7 @@
|
|
|
18
30
|
"e3": "node ./test/e3.js",
|
|
19
31
|
"e33": "node ./test/e33.js",
|
|
20
32
|
"e4": "node ./test/e4.js",
|
|
33
|
+
"e4async": "node ./test/e4async.mjs",
|
|
21
34
|
"e5": "node ./test/e5.js",
|
|
22
35
|
"build": "node build.js",
|
|
23
36
|
"build-dev": "node build-dev.js",
|
|
@@ -25,7 +38,7 @@
|
|
|
25
38
|
},
|
|
26
39
|
"gypfile": true,
|
|
27
40
|
"name": "mdbxmou",
|
|
28
|
-
"version": "0.2.
|
|
41
|
+
"version": "0.2.4",
|
|
29
42
|
"description": "Node bindings for mdbx",
|
|
30
43
|
"repository": {
|
|
31
44
|
"type": "git",
|