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 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
- envFlag: MDBX_Param.envFlag.nostickythreads
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
- - `envFlag` - Environment flags
77
- - `mapSize` - Maximum database size
78
- - `maxReaders` - Maximum number of readers
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], [flags], [name]) → DBI**
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, [name]) → DBI**
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", MDBX_Param.putFlag.nooverwrite);
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.readonly` - Open database in read-only mode
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.put` - Write operations
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
- // Patch CMakeLists.txt line 56: if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git" -> if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git"
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
- let cmakeContent = fs.readFileSync(cmakeFile, 'utf8').split('\n');
34
- if (cmakeContent[55] && cmakeContent[55].trim().startsWith('if(EXISTS')) {
35
- cmakeContent[55] = cmakeContent[55].replace('if(EXISTS', 'if(NOT EXISTS');
36
- fs.writeFileSync(cmakeFile, cmakeContent.join('\n'));
37
- console.log('Patched CMakeLists.txt line 56: if(NOT EXISTS ...');
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
@@ -0,0 +1,7 @@
1
+ import { createRequire } from "node:module";
2
+
3
+ const require = createRequire(import.meta.url);
4
+ const { MDBX_Async_Env } = require("./mdbx_evn_async.js");
5
+
6
+ export { MDBX_Async_Env };
7
+ export default MDBX_Async_Env;
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;
@@ -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.2",
41
+ "version": "0.2.4",
29
42
  "description": "Node bindings for mdbx",
30
43
  "repository": {
31
44
  "type": "git",