keri-ts 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 +202 -0
- package/README.md +70 -0
- package/esm/_dnt.polyfills.js +127 -0
- package/esm/_dnt.shims.js +61 -0
- package/esm/app/cli/agent.js +37 -0
- package/esm/app/cli/cli-node.js +9 -0
- package/esm/app/cli/cli.js +195 -0
- package/esm/app/cli/db-dump.js +68 -0
- package/esm/app/cli/init.js +75 -0
- package/esm/app/server.js +77 -0
- package/esm/core/bytes.js +39 -0
- package/esm/core/errors.js +26 -0
- package/esm/core/index.js +7 -0
- package/esm/db/basing.js +168 -0
- package/esm/db/core/db.js +19 -0
- package/esm/db/core/lmdber.js +474 -0
- package/esm/db/core/path-manager.js +450 -0
- package/esm/db/index.js +4 -0
- package/esm/npm/index.js +4 -0
- package/esm/package.json +3 -0
- package/package.json +57 -0
- package/types/_dnt.polyfills.d.ts +101 -0
- package/types/_dnt.polyfills.d.ts.map +1 -0
- package/types/_dnt.shims.d.ts +6 -0
- package/types/_dnt.shims.d.ts.map +1 -0
- package/types/app/cli/agent.d.ts +9 -0
- package/types/app/cli/agent.d.ts.map +1 -0
- package/types/app/cli/cli-node.d.ts +2 -0
- package/types/app/cli/cli-node.d.ts.map +1 -0
- package/types/app/cli/cli.d.ts +7 -0
- package/types/app/cli/cli.d.ts.map +1 -0
- package/types/app/cli/db-dump.d.ts +11 -0
- package/types/app/cli/db-dump.d.ts.map +1 -0
- package/types/app/cli/init.d.ts +3 -0
- package/types/app/cli/init.d.ts.map +1 -0
- package/types/app/server.d.ts +8 -0
- package/types/app/server.d.ts.map +1 -0
- package/types/core/bytes.d.ts +17 -0
- package/types/core/bytes.d.ts.map +1 -0
- package/types/core/errors.d.ts +19 -0
- package/types/core/errors.d.ts.map +1 -0
- package/types/core/index.d.ts +8 -0
- package/types/core/index.d.ts.map +1 -0
- package/types/db/basing.d.ts +80 -0
- package/types/db/basing.d.ts.map +1 -0
- package/types/db/core/db.d.ts +5 -0
- package/types/db/core/db.d.ts.map +1 -0
- package/types/db/core/lmdber.d.ts +135 -0
- package/types/db/core/lmdber.d.ts.map +1 -0
- package/types/db/core/path-manager.d.ts +92 -0
- package/types/db/core/path-manager.d.ts.map +1 -0
- package/types/db/index.d.ts +5 -0
- package/types/db/index.d.ts.map +1 -0
- package/types/npm/index.d.ts +5 -0
- package/types/npm/index.d.ts.map +1 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LMDBer - Core LMDB database manager
|
|
3
|
+
*
|
|
4
|
+
* Manages LMDB database environments and provides CRUD operations.
|
|
5
|
+
* Uses composition with PathManager instead of inheritance.
|
|
6
|
+
*/
|
|
7
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
8
|
+
import { open } from "lmdb";
|
|
9
|
+
import { startsWith } from "../../core/bytes.js";
|
|
10
|
+
import { DatabaseKeyError, DatabaseNotOpenError, DatabaseOperationError, } from "../../core/errors.js";
|
|
11
|
+
import { PathManager, } from "./path-manager.js";
|
|
12
|
+
// Module-level encoder/decoder instances (stateless, reusable)
|
|
13
|
+
const encoder = new TextEncoder();
|
|
14
|
+
const decoder = new TextDecoder();
|
|
15
|
+
// Short helpers for string ↔ Uint8Array conversion
|
|
16
|
+
// bytes from string/text (UTF-8)
|
|
17
|
+
export const b = (t) => encoder.encode(t);
|
|
18
|
+
// text/string from bytes (UTF-8)
|
|
19
|
+
export const t = (b) => decoder.decode(b);
|
|
20
|
+
export const LMDBER_DEFAULTS = {
|
|
21
|
+
headDirPath: "/usr/local/var",
|
|
22
|
+
tailDirPath: "keri/db",
|
|
23
|
+
cleanTailDirPath: "keri/clean/db",
|
|
24
|
+
altHeadDirPath: "~",
|
|
25
|
+
altTailDirPath: ".keri/db",
|
|
26
|
+
altCleanTailDirPath: ".keri/clean/db",
|
|
27
|
+
tempHeadDir: "/tmp",
|
|
28
|
+
tempPrefix: "keri_lmdb_",
|
|
29
|
+
tempSuffix: "_test",
|
|
30
|
+
perm: 0o1700,
|
|
31
|
+
mode: "r+",
|
|
32
|
+
fext: "text",
|
|
33
|
+
maxNamedDBs: 96,
|
|
34
|
+
mapSize: 4 * 1024 * 1024 * 1024, // 4GB default
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* LMDBer manages LMDB database environments
|
|
38
|
+
* Uses composition with PathManager for path management
|
|
39
|
+
*/
|
|
40
|
+
export class LMDBer {
|
|
41
|
+
constructor(options = {}, defaults) {
|
|
42
|
+
Object.defineProperty(this, "pathManager", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: void 0
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(this, "env", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: true,
|
|
52
|
+
value: void 0
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(this, "readonly", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
configurable: true,
|
|
57
|
+
writable: true,
|
|
58
|
+
value: void 0
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(this, "defaults", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
writable: true,
|
|
64
|
+
value: void 0
|
|
65
|
+
});
|
|
66
|
+
this.defaults = { ...LMDBER_DEFAULTS, ...defaults };
|
|
67
|
+
// Create PathManager with composition
|
|
68
|
+
const pathDefaults = {
|
|
69
|
+
headDirPath: this.defaults.headDirPath,
|
|
70
|
+
tailDirPath: this.defaults.tailDirPath,
|
|
71
|
+
cleanTailDirPath: this.defaults.cleanTailDirPath,
|
|
72
|
+
altHeadDirPath: this.defaults.altHeadDirPath,
|
|
73
|
+
altTailDirPath: this.defaults.altTailDirPath,
|
|
74
|
+
altCleanTailDirPath: this.defaults.altCleanTailDirPath,
|
|
75
|
+
tempHeadDir: this.defaults.tempHeadDir,
|
|
76
|
+
tempPrefix: this.defaults.tempPrefix,
|
|
77
|
+
tempSuffix: this.defaults.tempSuffix,
|
|
78
|
+
perm: this.defaults.perm,
|
|
79
|
+
};
|
|
80
|
+
this.pathManager = new PathManager(options, pathDefaults);
|
|
81
|
+
this.env = null;
|
|
82
|
+
this.readonly = options.readonly || false;
|
|
83
|
+
}
|
|
84
|
+
get name() {
|
|
85
|
+
return this.pathManager.name;
|
|
86
|
+
}
|
|
87
|
+
get base() {
|
|
88
|
+
return this.pathManager.base;
|
|
89
|
+
}
|
|
90
|
+
get opened() {
|
|
91
|
+
return this.pathManager.opened && this.env !== null;
|
|
92
|
+
}
|
|
93
|
+
get temp() {
|
|
94
|
+
return this.pathManager.temp;
|
|
95
|
+
}
|
|
96
|
+
get path() {
|
|
97
|
+
return this.pathManager.path;
|
|
98
|
+
}
|
|
99
|
+
formatDbKeyError(key, error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
return new DatabaseKeyError(`Key is empty, too big, or wrong size: ${message}`, { key: Array.from(key) });
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Reopen the LMDB database
|
|
105
|
+
* Closes existing database if open before opening a new one to prevent double-free errors
|
|
106
|
+
*/
|
|
107
|
+
*reopen(options = {}) {
|
|
108
|
+
const readonly = options.readonly ?? this.readonly;
|
|
109
|
+
this.readonly = readonly;
|
|
110
|
+
// Close existing database if open (prevents double-free when reopening)
|
|
111
|
+
if (this.env) {
|
|
112
|
+
try {
|
|
113
|
+
// Close synchronously - LMDB close() is synchronous
|
|
114
|
+
this.env.close();
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
// Ignore close errors (database might already be closed)
|
|
118
|
+
console.warn(`Warning: Error closing existing LMDB environment: ${error}`);
|
|
119
|
+
}
|
|
120
|
+
this.env = null;
|
|
121
|
+
}
|
|
122
|
+
// Reopen path manager (now an Effection operation)
|
|
123
|
+
yield* this.pathManager.reopen(options);
|
|
124
|
+
if (!this.pathManager.path) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
let dbPath = this.pathManager.path;
|
|
128
|
+
// Get map size from environment variable or use default
|
|
129
|
+
const mapSizeEnv = dntShim.Deno.env.get("KERI_LMDB_MAP_SIZE");
|
|
130
|
+
const mapSize = mapSizeEnv
|
|
131
|
+
? parseInt(mapSizeEnv, 10)
|
|
132
|
+
: this.defaults.mapSize;
|
|
133
|
+
// Check if database files exist before opening
|
|
134
|
+
const dbExists = yield* this.checkDatabaseExists();
|
|
135
|
+
// If readonly and database doesn't exist, we need to handle that gracefully
|
|
136
|
+
// For readonly mode, database files must exist
|
|
137
|
+
if (readonly && !dbExists) {
|
|
138
|
+
console.error(`Cannot open readonly database: database files do not exist at ${dbPath}`);
|
|
139
|
+
this.env = null;
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
// For readonly opens of existing databases, use a large mapSize that's safe
|
|
143
|
+
// LMDB will use the actual map size from the database file, but the Node.js
|
|
144
|
+
// lmdb package requires mapSize to be >= the database's actual map size
|
|
145
|
+
// Use 4GB (KERIpy default) or larger to ensure compatibility
|
|
146
|
+
const effectiveMapSize = readonly && dbExists
|
|
147
|
+
? Math.max(mapSize, 4 * 1024 * 1024 * 1024) // At least 4GB for existing databases
|
|
148
|
+
: mapSize;
|
|
149
|
+
const dbConfig = {
|
|
150
|
+
path: dbPath, // Use directory path (Node.js lmdb should handle this)
|
|
151
|
+
maxDbs: this.defaults.maxNamedDBs,
|
|
152
|
+
mapSize: effectiveMapSize,
|
|
153
|
+
readOnly: readonly,
|
|
154
|
+
compression: false, // Disable compression for compatibility
|
|
155
|
+
encoding: "binary", // to mimic KERIpy behavior
|
|
156
|
+
keyEncoding: "binary", // to mimic KERIpy behavior
|
|
157
|
+
};
|
|
158
|
+
console.log(`Opening LMDB at: ${dbPath} (readonly: ${readonly}, mapSize: ${effectiveMapSize})`);
|
|
159
|
+
// Open LMDB environment
|
|
160
|
+
// LMDB's open() will create data.mdb and lock.mdb if they don't exist
|
|
161
|
+
try {
|
|
162
|
+
// do sync because wrapping synchronous native operations in action() can cause
|
|
163
|
+
// memory management issues with native bindings (double-free errors)
|
|
164
|
+
this.env = open(dbConfig);
|
|
165
|
+
console.log(`LMDB environment opened successfully`);
|
|
166
|
+
// Set version if new database and not readonly
|
|
167
|
+
if (this.opened && !readonly && !dbExists && !this.temp) {
|
|
168
|
+
// Set version for new database
|
|
169
|
+
const version = "1.0.0"; // Default version
|
|
170
|
+
this.setVer(version);
|
|
171
|
+
}
|
|
172
|
+
return this.opened;
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
console.error(`Failed to open LMDB: ${error}`);
|
|
176
|
+
this.env = null;
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Check if database already exists by checking for database files
|
|
182
|
+
*/
|
|
183
|
+
*checkDatabaseExists() {
|
|
184
|
+
if (!this.pathManager.path) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
// Check if database files exist (now an Effection operation)
|
|
188
|
+
return yield* this.pathManager.databaseFilesExist();
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Close the LMDB database
|
|
192
|
+
*/
|
|
193
|
+
*close(clear = false) {
|
|
194
|
+
if (this.env) {
|
|
195
|
+
try {
|
|
196
|
+
this.env.close();
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
// Ignore close errors (database might already be closed)
|
|
200
|
+
console.warn(`Error closing LMDB: ${error}`);
|
|
201
|
+
}
|
|
202
|
+
this.env = null;
|
|
203
|
+
}
|
|
204
|
+
// Close path manager (now an Effection operation)
|
|
205
|
+
yield* this.pathManager.close(clear);
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get database version
|
|
210
|
+
*/
|
|
211
|
+
getVer() {
|
|
212
|
+
const env = this.env;
|
|
213
|
+
try {
|
|
214
|
+
const versionBytes = env.get(b("__version__"));
|
|
215
|
+
const version = t(versionBytes);
|
|
216
|
+
return version || null;
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Set database version
|
|
224
|
+
*/
|
|
225
|
+
setVer(val) {
|
|
226
|
+
const env = this.env;
|
|
227
|
+
try {
|
|
228
|
+
env.transactionSync(() => {
|
|
229
|
+
env.putSync(b("__version__"), b(val));
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
234
|
+
throw new DatabaseOperationError(`Failed to set database version: ${message}`, { version: val });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Open a named sub-database
|
|
239
|
+
*/
|
|
240
|
+
openDB(name, dupsort = false) {
|
|
241
|
+
const env = this.env;
|
|
242
|
+
return env.openDB(name, {
|
|
243
|
+
keyEncoding: "binary",
|
|
244
|
+
encoding: "binary", // Use binary encoding for values (raw bytes) to match KERIpy
|
|
245
|
+
dupSort: dupsort,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Put value (no overwrite)
|
|
250
|
+
*
|
|
251
|
+
* @param db - Named sub-database
|
|
252
|
+
* @param key - Key bytes
|
|
253
|
+
* @param val - Value bytes
|
|
254
|
+
* @returns True if successfully written, False if key already exists
|
|
255
|
+
*/
|
|
256
|
+
putVal(db, key, val) {
|
|
257
|
+
const env = this.env;
|
|
258
|
+
try {
|
|
259
|
+
const result = env.transactionSync(() => {
|
|
260
|
+
const existing = db.get(key);
|
|
261
|
+
if (existing !== null && existing !== undefined) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
db.put(key, val);
|
|
265
|
+
return true;
|
|
266
|
+
});
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
throw this.formatDbKeyError(key, error);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Set value (overwrite allowed)
|
|
275
|
+
*
|
|
276
|
+
* @param db - Named sub-database
|
|
277
|
+
* @param key - Key bytes
|
|
278
|
+
* @param val - Value bytes
|
|
279
|
+
* @returns True if successfully written
|
|
280
|
+
*/
|
|
281
|
+
setVal(db, key, val) {
|
|
282
|
+
const env = this.env;
|
|
283
|
+
try {
|
|
284
|
+
env.transactionSync(() => {
|
|
285
|
+
db.put(key, val);
|
|
286
|
+
});
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
throw this.formatDbKeyError(key, error);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Get value
|
|
295
|
+
*
|
|
296
|
+
* @param db - Named sub-database
|
|
297
|
+
* @param key - Key bytes
|
|
298
|
+
* @returns Value bytes or null if not found
|
|
299
|
+
*/
|
|
300
|
+
getVal(db, key) {
|
|
301
|
+
try {
|
|
302
|
+
const val = db.get(key);
|
|
303
|
+
if (val === null || val === undefined) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
return val instanceof Uint8Array ? val : new Uint8Array(val);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
throw this.formatDbKeyError(key, error);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Delete value
|
|
316
|
+
*
|
|
317
|
+
* @param db - Named sub-database
|
|
318
|
+
* @param key - Key bytes
|
|
319
|
+
* @returns True if key existed, False otherwise
|
|
320
|
+
*/
|
|
321
|
+
delVal(db, key) {
|
|
322
|
+
const env = this.env;
|
|
323
|
+
try {
|
|
324
|
+
const result = env.transactionSync(() => {
|
|
325
|
+
const exists = db.get(key) !== null && db.get(key) !== undefined;
|
|
326
|
+
if (exists) {
|
|
327
|
+
db.remove(key);
|
|
328
|
+
}
|
|
329
|
+
return exists;
|
|
330
|
+
});
|
|
331
|
+
return result;
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
throw this.formatDbKeyError(key, error);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Count all values in database
|
|
339
|
+
*
|
|
340
|
+
* @param db - Named sub-database
|
|
341
|
+
* @returns Count of entries
|
|
342
|
+
*/
|
|
343
|
+
cnt(db) {
|
|
344
|
+
try {
|
|
345
|
+
let count = 0;
|
|
346
|
+
for (const _ of db.getRange({})) {
|
|
347
|
+
count++;
|
|
348
|
+
}
|
|
349
|
+
return count;
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
353
|
+
throw new DatabaseOperationError(`Failed to count database entries: ${message}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Iterates over branch of db given by top key
|
|
358
|
+
*
|
|
359
|
+
* Returns iterator of (full key, val) tuples over a branch of the db given by top key
|
|
360
|
+
* where: full key is full database key for val not truncated top key.
|
|
361
|
+
*
|
|
362
|
+
* Works for both dupsort==False and dupsort==True
|
|
363
|
+
* Because cursor.iternext() advances cursor after returning item its safe
|
|
364
|
+
* to delete the item within the iteration loop.
|
|
365
|
+
*
|
|
366
|
+
* @param db - Named sub-database
|
|
367
|
+
* @param top - Truncated top key, a key space prefix to get all the items
|
|
368
|
+
* from multiple branches of the key space. If top key is
|
|
369
|
+
* empty then gets all items in database.
|
|
370
|
+
* Empty Uint8Array matches all keys (like str.startswith('') always returns True)
|
|
371
|
+
* @returns Generator yielding (key, val) tuples
|
|
372
|
+
*/
|
|
373
|
+
*getTopItemIter(db, top = new Uint8Array(0)) {
|
|
374
|
+
try {
|
|
375
|
+
// Use getRange with start position at top key
|
|
376
|
+
// With binary encoding, keys and values are always Uint8Array
|
|
377
|
+
const startKey = top.length > 0 ? top : undefined;
|
|
378
|
+
for (const entry of db.getRange({ start: startKey })) {
|
|
379
|
+
const keyBytes = entry.key;
|
|
380
|
+
const valBytes = entry.value;
|
|
381
|
+
// Check if key starts with top prefix
|
|
382
|
+
// If top is empty, match all keys (empty prefix matches everything)
|
|
383
|
+
if (top.length > 0 && !startsWith(keyBytes, top)) {
|
|
384
|
+
break; // Done - no more keys in this branch
|
|
385
|
+
}
|
|
386
|
+
yield [keyBytes, valBytes];
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
// If iteration fails, return empty generator
|
|
391
|
+
console.warn(`Error iterating database: ${error}`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// Class constants
|
|
396
|
+
Object.defineProperty(LMDBer, "HeadDirPath", {
|
|
397
|
+
enumerable: true,
|
|
398
|
+
configurable: true,
|
|
399
|
+
writable: true,
|
|
400
|
+
value: "/usr/local/var"
|
|
401
|
+
});
|
|
402
|
+
Object.defineProperty(LMDBer, "TailDirPath", {
|
|
403
|
+
enumerable: true,
|
|
404
|
+
configurable: true,
|
|
405
|
+
writable: true,
|
|
406
|
+
value: "keri/db"
|
|
407
|
+
});
|
|
408
|
+
Object.defineProperty(LMDBer, "CleanTailDirPath", {
|
|
409
|
+
enumerable: true,
|
|
410
|
+
configurable: true,
|
|
411
|
+
writable: true,
|
|
412
|
+
value: "keri/clean/db"
|
|
413
|
+
});
|
|
414
|
+
Object.defineProperty(LMDBer, "AltHeadDirPath", {
|
|
415
|
+
enumerable: true,
|
|
416
|
+
configurable: true,
|
|
417
|
+
writable: true,
|
|
418
|
+
value: "~"
|
|
419
|
+
});
|
|
420
|
+
Object.defineProperty(LMDBer, "AltTailDirPath", {
|
|
421
|
+
enumerable: true,
|
|
422
|
+
configurable: true,
|
|
423
|
+
writable: true,
|
|
424
|
+
value: ".keri/db"
|
|
425
|
+
});
|
|
426
|
+
Object.defineProperty(LMDBer, "AltCleanTailDirPath", {
|
|
427
|
+
enumerable: true,
|
|
428
|
+
configurable: true,
|
|
429
|
+
writable: true,
|
|
430
|
+
value: ".keri/clean/db"
|
|
431
|
+
});
|
|
432
|
+
Object.defineProperty(LMDBer, "TempHeadDir", {
|
|
433
|
+
enumerable: true,
|
|
434
|
+
configurable: true,
|
|
435
|
+
writable: true,
|
|
436
|
+
value: "/tmp"
|
|
437
|
+
});
|
|
438
|
+
Object.defineProperty(LMDBer, "TempPrefix", {
|
|
439
|
+
enumerable: true,
|
|
440
|
+
configurable: true,
|
|
441
|
+
writable: true,
|
|
442
|
+
value: "keri_lmdb_"
|
|
443
|
+
});
|
|
444
|
+
Object.defineProperty(LMDBer, "TempSuffix", {
|
|
445
|
+
enumerable: true,
|
|
446
|
+
configurable: true,
|
|
447
|
+
writable: true,
|
|
448
|
+
value: "_test"
|
|
449
|
+
});
|
|
450
|
+
Object.defineProperty(LMDBer, "Perm", {
|
|
451
|
+
enumerable: true,
|
|
452
|
+
configurable: true,
|
|
453
|
+
writable: true,
|
|
454
|
+
value: 0o1700
|
|
455
|
+
});
|
|
456
|
+
Object.defineProperty(LMDBer, "MaxNamedDBs", {
|
|
457
|
+
enumerable: true,
|
|
458
|
+
configurable: true,
|
|
459
|
+
writable: true,
|
|
460
|
+
value: 96
|
|
461
|
+
});
|
|
462
|
+
/**
|
|
463
|
+
* Create and open an LMDBer instance.
|
|
464
|
+
*
|
|
465
|
+
* Constructors cannot be async, so call this factory where an opened LMDBer is required.
|
|
466
|
+
*/
|
|
467
|
+
export function* createLMDBer(options = {}, defaults) {
|
|
468
|
+
const lmdber = new LMDBer(options, defaults);
|
|
469
|
+
const opened = yield* lmdber.reopen(options);
|
|
470
|
+
if (!opened) {
|
|
471
|
+
throw new DatabaseNotOpenError("Failed to open LMDBer");
|
|
472
|
+
}
|
|
473
|
+
return lmdber;
|
|
474
|
+
}
|