keri-ts 2.0.1 → 2.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/esm/keri/npm/src/acdc/chaining.js +223 -89
- package/esm/keri/npm/src/acdc/observing.js +2 -2
- package/esm/keri/npm/src/acdc/regbasing.js +20 -29
- package/esm/keri/npm/src/acdc/regengine.js +4 -6
- package/esm/keri/npm/src/acdc/registering.js +13 -10
- package/esm/keri/npm/src/acdc/registraring.js +4 -9
- package/esm/keri/npm/src/acdc/salting.js +127 -25
- package/esm/keri/npm/src/acdc/unblinding.js +2 -4
- package/esm/keri/npm/src/app/bootstrap/oobiery.js +1 -1
- package/esm/keri/npm/src/app/credentials/root-replicating.js +123 -0
- package/esm/keri/npm/src/app/credentials/verifying.js +12 -3
- package/esm/keri/npm/src/app/delivery/forwarding.js +49 -7
- package/esm/keri/npm/src/app/exchanges/exchanging.js +11 -12
- package/esm/keri/npm/src/app/identity/configing.js +17 -43
- package/esm/keri/npm/src/app/identity/habbing.js +54 -35
- package/esm/keri/npm/src/app/identity/keeping.js +1 -1
- package/esm/keri/npm/src/app/identity/lmdb-habery.js +12 -0
- package/esm/keri/npm/src/app/ipex/ipex-graph.js +7 -70
- package/esm/keri/npm/src/app/ipex/ipex-grouping.js +8 -5
- package/esm/keri/npm/src/app/ipex/ipex-v2.js +21 -5
- package/esm/keri/npm/src/app/ipex/ipexing.js +1 -1
- package/esm/keri/npm/src/app/mailbox/mailboxing.js +5 -9
- package/esm/keri/npm/src/app/multisig/group-members.js +14 -0
- package/esm/keri/npm/src/app/multisig/grouping.js +4 -3
- package/esm/keri/npm/src/app/multisig/multisig-workflows.js +7 -2
- package/esm/keri/npm/src/app/notifications/notifying.js +5 -9
- package/esm/keri/npm/src/app/protocol/protocol-processing.js +35 -3
- package/esm/keri/npm/src/app/queries/witness-inquisitor.js +2 -2
- package/esm/keri/npm/src/app/runtime/agent-runtime.js +7 -10
- package/esm/keri/npm/src/app/transport/byte-source.js +6 -42
- package/esm/keri/npm/src/app/transport/cesr-egress.js +77 -13
- package/esm/keri/npm/src/app/transport/file-bytes.js +41 -0
- package/esm/keri/npm/src/app/transport/http-messenger.js +14 -9
- package/esm/keri/npm/src/app/transport/message-source.js +1 -1
- package/esm/keri/npm/src/app/transport/messengering.js +3 -4
- package/esm/keri/npm/src/app/transport/node-http-client.js +21 -0
- package/esm/keri/npm/src/app/transport/tcp-dialer.js +14 -0
- package/esm/keri/npm/src/app/witness/receipt-client.js +2 -2
- package/esm/keri/npm/src/cli/common/context.js +2 -2
- package/esm/keri/npm/src/cli/common/existing.js +3 -5
- package/esm/keri/npm/src/cli/credentials/ipex.js +2 -1
- package/esm/keri/npm/src/cli/endpoints/oobi-clean.js +4 -3
- package/esm/keri/npm/src/cli/endpoints/oobi.js +2 -2
- package/esm/keri/npm/src/cli/identity/challenge.js +2 -2
- package/esm/keri/npm/src/cli/identity/incept.js +2 -2
- package/esm/keri/npm/src/cli/identity/init.js +4 -3
- package/esm/keri/npm/src/cli/identity/interact.js +2 -2
- package/esm/keri/npm/src/cli/identity/rotate.js +2 -2
- package/esm/keri/npm/src/cli/messaging/exchange.js +2 -2
- package/esm/keri/npm/src/cli/messaging/multisig.js +61 -3
- package/esm/keri/npm/src/cli/tools/annotate.js +2 -1
- package/esm/keri/npm/src/cli/tools/benchmark.js +2 -1
- package/esm/keri/npm/src/cli/tools/db-dump.js +1 -4
- package/esm/keri/npm/src/core/bytes.js +9 -0
- package/esm/keri/npm/src/core/kel/delegation-ancestry.js +92 -0
- package/esm/keri/npm/src/core/kel/eventing.js +1 -2
- package/esm/keri/npm/src/core/kel/kever.js +11 -9
- package/esm/keri/npm/src/core/mailbox/kram-policy.js +2 -3
- package/esm/keri/npm/src/core/mailbox/kram-pruning.js +15 -22
- package/esm/keri/npm/src/core/mailbox/kram-staging.js +2 -2
- package/esm/keri/npm/src/core/routing.js +2 -2
- package/esm/keri/npm/src/db/basing.js +149 -203
- package/esm/keri/npm/src/db/core/dber.js +1062 -0
- package/esm/keri/npm/src/db/core/index.js +4 -2
- package/esm/keri/npm/src/db/core/lmdb-opener.js +30 -0
- package/esm/keri/npm/src/db/core/lmdber.js +199 -1067
- package/esm/keri/npm/src/db/core/memstore.js +532 -0
- package/esm/keri/npm/src/db/core/path-manager.js +109 -223
- package/esm/keri/npm/src/db/core/store-owner.js +104 -0
- package/esm/keri/npm/src/db/core/webdber.js +252 -0
- package/esm/keri/npm/src/db/escrowing.js +2 -2
- package/esm/keri/npm/src/db/exchange/exchange-nests.js +3 -2
- package/esm/keri/npm/src/db/keeping.js +27 -121
- package/esm/keri/npm/src/db/koming.js +1 -1
- package/esm/keri/npm/src/db/lmdb-stores.js +68 -0
- package/esm/keri/npm/src/db/lmdb.js +6 -0
- package/esm/keri/npm/src/db/mailbox/mailboxing.js +12 -65
- package/esm/keri/npm/src/db/noting.js +11 -55
- package/esm/keri/npm/src/db/reger.js +43 -105
- package/esm/keri/npm/src/db/replay/witness-replay.js +2 -20
- package/esm/keri/npm/src/db/subing.js +1 -1
- package/esm/keri/npm/src/npm/db-lmdb.js +3 -0
- package/esm/keri/npm/src/npm/runtime-node.js +3 -0
- package/esm/keri/npm/src/runtime/index.js +9 -10
- package/esm/keri/npm/src/runtime/node.js +14 -0
- package/esm/keri/npm/src/vdr/eventing.js +1 -1
- package/esm/keri/npm/src/vdr/tel-publication.js +3 -3
- package/esm/keri/npm/src/version.js +2 -2
- package/package.json +11 -4
- package/types/acdc/chaining.d.ts +56 -6
- package/types/acdc/chaining.d.ts.map +1 -1
- package/types/acdc/regbasing.d.ts +7 -6
- package/types/acdc/regbasing.d.ts.map +1 -1
- package/types/acdc/regengine.d.ts.map +1 -1
- package/types/acdc/registering.d.ts +8 -4
- package/types/acdc/registering.d.ts.map +1 -1
- package/types/acdc/registraring.d.ts.map +1 -1
- package/types/acdc/salting.d.ts +53 -6
- package/types/acdc/salting.d.ts.map +1 -1
- package/types/acdc/unblinding.d.ts.map +1 -1
- package/types/app/credentials/root-replicating.d.ts +85 -0
- package/types/app/credentials/root-replicating.d.ts.map +1 -0
- package/types/app/credentials/verifying.d.ts +2 -1
- package/types/app/credentials/verifying.d.ts.map +1 -1
- package/types/app/delivery/forwarding.d.ts +10 -0
- package/types/app/delivery/forwarding.d.ts.map +1 -1
- package/types/app/exchanges/exchanging.d.ts +2 -0
- package/types/app/exchanges/exchanging.d.ts.map +1 -1
- package/types/app/identity/configing.d.ts +7 -5
- package/types/app/identity/configing.d.ts.map +1 -1
- package/types/app/identity/habbing.d.ts +23 -5
- package/types/app/identity/habbing.d.ts.map +1 -1
- package/types/app/identity/keeping.d.ts +1 -1
- package/types/app/identity/lmdb-habery.d.ts +6 -0
- package/types/app/identity/lmdb-habery.d.ts.map +1 -0
- package/types/app/ipex/ipex-graph.d.ts +4 -4
- package/types/app/ipex/ipex-graph.d.ts.map +1 -1
- package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
- package/types/app/ipex/ipex-v2.d.ts +11 -2
- package/types/app/ipex/ipex-v2.d.ts.map +1 -1
- package/types/app/ipex/ipexing.d.ts +3 -0
- package/types/app/ipex/ipexing.d.ts.map +1 -1
- package/types/app/mailbox/mailboxing.d.ts +1 -1
- package/types/app/mailbox/mailboxing.d.ts.map +1 -1
- package/types/app/multisig/group-members.d.ts +9 -0
- package/types/app/multisig/group-members.d.ts.map +1 -1
- package/types/app/multisig/grouping.d.ts.map +1 -1
- package/types/app/multisig/multisig-workflows.d.ts +2 -1
- package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
- package/types/app/notifications/notifying.d.ts +1 -1
- package/types/app/notifications/notifying.d.ts.map +1 -1
- package/types/app/protocol/parsering.d.ts +3 -1
- package/types/app/protocol/parsering.d.ts.map +1 -1
- package/types/app/protocol/protocol-processing.d.ts +2 -0
- package/types/app/protocol/protocol-processing.d.ts.map +1 -1
- package/types/app/runtime/agent-runtime.d.ts +7 -0
- package/types/app/runtime/agent-runtime.d.ts.map +1 -1
- package/types/app/transport/byte-source.d.ts +13 -10
- package/types/app/transport/byte-source.d.ts.map +1 -1
- package/types/app/transport/cesr-egress.d.ts +21 -7
- package/types/app/transport/cesr-egress.d.ts.map +1 -1
- package/types/app/transport/file-bytes.d.ts +11 -0
- package/types/app/transport/file-bytes.d.ts.map +1 -0
- package/types/app/transport/http-client.d.ts +3 -0
- package/types/app/transport/http-client.d.ts.map +1 -1
- package/types/app/transport/http-messenger.d.ts +15 -10
- package/types/app/transport/http-messenger.d.ts.map +1 -1
- package/types/app/transport/message-source.d.ts +1 -1
- package/types/app/transport/messengering.d.ts +2 -2
- package/types/app/transport/messengering.d.ts.map +1 -1
- package/types/app/transport/node-http-client.d.ts +10 -0
- package/types/app/transport/node-http-client.d.ts.map +1 -0
- package/types/app/transport/tcp-dialer.d.ts +21 -0
- package/types/app/transport/tcp-dialer.d.ts.map +1 -0
- package/types/cli/common/existing.d.ts.map +1 -1
- package/types/cli/credentials/ipex.d.ts.map +1 -1
- package/types/cli/endpoints/oobi-clean.d.ts.map +1 -1
- package/types/cli/identity/init.d.ts.map +1 -1
- package/types/cli/index.d.ts +1 -1
- package/types/cli/index.d.ts.map +1 -1
- package/types/cli/messaging/multisig.d.ts +10 -1
- package/types/cli/messaging/multisig.d.ts.map +1 -1
- package/types/cli/tools/annotate.d.ts.map +1 -1
- package/types/cli/tools/benchmark.d.ts.map +1 -1
- package/types/cli/tools/db-dump.d.ts.map +1 -1
- package/types/core/bytes.d.ts +2 -0
- package/types/core/bytes.d.ts.map +1 -1
- package/types/core/kel/delegation-ancestry.d.ts +41 -0
- package/types/core/kel/delegation-ancestry.d.ts.map +1 -0
- package/types/core/kel/eventing.d.ts.map +1 -1
- package/types/core/kel/kever.d.ts +5 -4
- package/types/core/kel/kever.d.ts.map +1 -1
- package/types/core/mailbox/kram-policy.d.ts.map +1 -1
- package/types/core/mailbox/kram-pruning.d.ts +1 -3
- package/types/core/mailbox/kram-pruning.d.ts.map +1 -1
- package/types/db/basing.d.ts +14 -23
- package/types/db/basing.d.ts.map +1 -1
- package/types/db/core/dber.d.ts +505 -0
- package/types/db/core/dber.d.ts.map +1 -0
- package/types/db/core/index.d.ts +4 -2
- package/types/db/core/index.d.ts.map +1 -1
- package/types/db/core/lmdb-opener.d.ts +17 -0
- package/types/db/core/lmdb-opener.d.ts.map +1 -0
- package/types/db/core/lmdber.d.ts +60 -383
- package/types/db/core/lmdber.d.ts.map +1 -1
- package/types/db/core/memstore.d.ts +129 -0
- package/types/db/core/memstore.d.ts.map +1 -0
- package/types/db/core/path-manager.d.ts +22 -45
- package/types/db/core/path-manager.d.ts.map +1 -1
- package/types/db/core/store-owner.d.ts +59 -0
- package/types/db/core/store-owner.d.ts.map +1 -0
- package/types/db/core/webdber.d.ts +127 -0
- package/types/db/core/webdber.d.ts.map +1 -0
- package/types/db/escrowing.d.ts +3 -3
- package/types/db/escrowing.d.ts.map +1 -1
- package/types/db/exchange/exchange-nests.d.ts.map +1 -1
- package/types/db/keeping.d.ts +9 -23
- package/types/db/keeping.d.ts.map +1 -1
- package/types/db/koming.d.ts +7 -8
- package/types/db/koming.d.ts.map +1 -1
- package/types/db/lmdb-stores.d.ts +45 -0
- package/types/db/lmdb-stores.d.ts.map +1 -0
- package/types/db/lmdb.d.ts +7 -0
- package/types/db/lmdb.d.ts.map +1 -0
- package/types/db/mailbox/mailboxing.d.ts +7 -21
- package/types/db/mailbox/mailboxing.d.ts.map +1 -1
- package/types/db/noting.d.ts +7 -12
- package/types/db/noting.d.ts.map +1 -1
- package/types/db/reger.d.ts +7 -11
- package/types/db/reger.d.ts.map +1 -1
- package/types/db/replay/witness-replay.d.ts +0 -2
- package/types/db/replay/witness-replay.d.ts.map +1 -1
- package/types/db/subing.d.ts +24 -25
- package/types/db/subing.d.ts.map +1 -1
- package/types/npm/db-lmdb.d.ts +4 -0
- package/types/npm/db-lmdb.d.ts.map +1 -0
- package/types/npm/runtime-node.d.ts +4 -0
- package/types/npm/runtime-node.d.ts.map +1 -0
- package/types/runtime/index.d.ts +9 -10
- package/types/runtime/index.d.ts.map +1 -1
- package/types/runtime/node.d.ts +15 -0
- package/types/runtime/node.d.ts.map +1 -0
- package/types/version.d.ts +2 -2
- package/esm/keri/npm/src/acdc/relating.js +0 -59
- package/esm/keri/npm/src/db/baser-defaults.js +0 -11
- package/types/acdc/relating.d.ts +0 -21
- package/types/acdc/relating.d.ts.map +0 -1
- package/types/db/baser-defaults.d.ts +0 -5
- package/types/db/baser-defaults.d.ts.map +0 -1
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Uses composition pattern instead of inheritance.
|
|
6
6
|
*/
|
|
7
7
|
import * as dntShim from "../../_dnt.shims.js";
|
|
8
|
-
import { isAbsolute, join } from "../../deps/jsr.io/@std/path/1.1.6/mod.js";
|
|
8
|
+
import { dirname, extname, isAbsolute, join, resolve } from "../../deps/jsr.io/@std/path/1.1.6/mod.js";
|
|
9
|
+
import { accessSync, constants } from "node:fs";
|
|
9
10
|
import { action } from "effection";
|
|
10
11
|
import { InvalidPathNameError, PathError } from "../../core/errors.js";
|
|
11
12
|
import { consoleLogger } from "../../core/logger.js";
|
|
@@ -20,9 +21,27 @@ function isNotFoundLike(error) {
|
|
|
20
21
|
return error instanceof dntShim.Deno.errors.NotFound
|
|
21
22
|
|| hasErrorCode(error, ["ENOENT"]);
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
/** The temp root hio uses: `/tmp` on macOS, otherwise Python's `tempfile.gettempdir` order. */
|
|
25
|
+
function tempHeadDir() {
|
|
26
|
+
if (dntShim.Deno.build.os === "darwin")
|
|
27
|
+
return "/tmp";
|
|
28
|
+
return dntShim.Deno.env.get("TMPDIR") || dntShim.Deno.env.get("TEMP") || dntShim.Deno.env.get("TMP") || "/tmp";
|
|
29
|
+
}
|
|
30
|
+
/** True when this process may read and write `path`, like `os.access(path, F_OK | R_OK | W_OK)`. */
|
|
31
|
+
function isAccessible(path) {
|
|
32
|
+
try {
|
|
33
|
+
accessSync(path, constants.F_OK | constants.R_OK | constants.W_OK);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Refuse an absolute name or base, which would escape the head directory. */
|
|
41
|
+
function assertRelative(value, label) {
|
|
42
|
+
if (isAbsolute(value) || /^[a-zA-Z]:[\\/]/.test(value)) {
|
|
43
|
+
throw new InvalidPathNameError(`Not relative ${label}=${value} path.`);
|
|
44
|
+
}
|
|
26
45
|
}
|
|
27
46
|
/** Defaults for the path manager */
|
|
28
47
|
export const PATH_DEFAULTS = {
|
|
@@ -32,7 +51,6 @@ export const PATH_DEFAULTS = {
|
|
|
32
51
|
altHeadDirPath: "~",
|
|
33
52
|
altTailDirPath: ".tufa/db",
|
|
34
53
|
altCleanTailDirPath: ".tufa/clean/db",
|
|
35
|
-
tempHeadDir: "/tmp",
|
|
36
54
|
tempPrefix: "keri_lmdb_",
|
|
37
55
|
tempSuffix: "_test",
|
|
38
56
|
perm: 0o1700, // sticky + owner rwx
|
|
@@ -50,10 +68,11 @@ export const PATH_DEFAULTS = {
|
|
|
50
68
|
* - centralize path naming constraints so higher-level DB/config wrappers do
|
|
51
69
|
* not each reimplement filesystem policy
|
|
52
70
|
*
|
|
53
|
-
* Current `keri-ts`
|
|
54
|
-
* -
|
|
55
|
-
*
|
|
56
|
-
*
|
|
71
|
+
* Current `keri-ts` differences from hio `Filer`, which it otherwise follows:
|
|
72
|
+
* - composition rather than inheritance, so stores own one instance
|
|
73
|
+
* - a temp store uses one stable directory per name instead of a fresh
|
|
74
|
+
* `mkdtemp` per open, so its data survives a close and reopen; temp stores are
|
|
75
|
+
* never shared with KERIpy
|
|
57
76
|
*/
|
|
58
77
|
export class PathManager {
|
|
59
78
|
constructor(options = {}, defaults) {
|
|
@@ -148,11 +167,20 @@ export class PathManager {
|
|
|
148
167
|
writable: true,
|
|
149
168
|
value: void 0
|
|
150
169
|
});
|
|
170
|
+
// the temporary directory holding `path`, when temp
|
|
171
|
+
Object.defineProperty(this, "tempRoot", {
|
|
172
|
+
enumerable: true,
|
|
173
|
+
configurable: true,
|
|
174
|
+
writable: true,
|
|
175
|
+
value: null
|
|
176
|
+
});
|
|
151
177
|
this.defaults = { ...PATH_DEFAULTS, ...defaults };
|
|
152
|
-
this._name = options.name
|
|
153
|
-
this.base = options.base
|
|
178
|
+
this._name = options.name ?? "main";
|
|
179
|
+
this.base = options.base ?? "";
|
|
180
|
+
assertRelative(this._name, "name");
|
|
181
|
+
assertRelative(this.base, "base");
|
|
154
182
|
this.temp = options.temp || false;
|
|
155
|
-
this.headDirPath = options.headDirPath
|
|
183
|
+
this.headDirPath = options.headDirPath ?? this.defaults.headDirPath;
|
|
156
184
|
this.perm = options.perm ?? this.defaults.perm;
|
|
157
185
|
this.path = null;
|
|
158
186
|
this.filed = options.filed || false;
|
|
@@ -168,18 +196,9 @@ export class PathManager {
|
|
|
168
196
|
return this._name;
|
|
169
197
|
}
|
|
170
198
|
set name(value) {
|
|
171
|
-
|
|
172
|
-
if (isAbsolute(value) || /^[a-zA-Z]:[\\/]/.test(value)) {
|
|
173
|
-
throw new InvalidPathNameError(`Not relative name=${value} path.`);
|
|
174
|
-
}
|
|
199
|
+
assertRelative(value, "name");
|
|
175
200
|
this._name = value;
|
|
176
201
|
}
|
|
177
|
-
_getTempPath() {
|
|
178
|
-
const tempDir = dntShim.Deno.env.get("TMPDIR") || dntShim.Deno.env.get("TMP")
|
|
179
|
-
|| dntShim.Deno.env.get("TEMP") || "/tmp";
|
|
180
|
-
const tempName = `${this.defaults.tempPrefix}${this.name}${this.defaults.tempSuffix}`;
|
|
181
|
-
return join(tempDir, tempName);
|
|
182
|
-
}
|
|
183
202
|
/** Resolve user home directory with a Windows-aware fallback chain. */
|
|
184
203
|
_resolveHomeDir() {
|
|
185
204
|
const home = dntShim.Deno.env.get("HOME");
|
|
@@ -205,95 +224,21 @@ export class PathManager {
|
|
|
205
224
|
}
|
|
206
225
|
return path;
|
|
207
226
|
}
|
|
208
|
-
_getPrimaryPath(headDirPath, clean) {
|
|
209
|
-
// head / tail / base / name
|
|
210
|
-
// Expand ~ to HOME directory
|
|
211
|
-
let head = headDirPath;
|
|
212
|
-
head = this._pathExpandTilde(head);
|
|
213
|
-
let tail;
|
|
214
|
-
if (clean) {
|
|
215
|
-
tail = this.defaults.cleanTailDirPath;
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
tail = this.defaults.tailDirPath;
|
|
219
|
-
}
|
|
220
|
-
return this.base
|
|
221
|
-
? join(head, tail, this.base, this.name)
|
|
222
|
-
: join(head, tail, this.name);
|
|
223
|
-
}
|
|
224
|
-
_getAltPath(clean) {
|
|
225
|
-
// HOME or ~ / tail / base / name
|
|
226
|
-
let head = dntShim.Deno.env.get("HOME") || "~";
|
|
227
|
-
head = this._pathExpandTilde(head);
|
|
228
|
-
let tail;
|
|
229
|
-
if (clean) {
|
|
230
|
-
tail = this.defaults.altCleanTailDirPath;
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
tail = this.defaults.altTailDirPath;
|
|
234
|
-
}
|
|
235
|
-
return this.base
|
|
236
|
-
? join(head, tail, this.base, this.name)
|
|
237
|
-
: join(head, tail, this.name);
|
|
238
|
-
}
|
|
239
|
-
/*
|
|
240
|
-
* Creates a file path based on head, tail, base, and name. Ensure path is created and optionally reuse it.
|
|
241
|
-
* @param options path creation options
|
|
242
|
-
* @returns File path to a persistent file or directory
|
|
243
|
-
*/
|
|
244
|
-
_getPersistentPaths(options = {}) {
|
|
245
|
-
const headDirPath = options.headDirPath ?? this.headDirPath;
|
|
246
|
-
const clean = options.clean || false;
|
|
247
|
-
const primary = this._getPrimaryPath(headDirPath, clean);
|
|
248
|
-
const alt = this._getAltPath(clean);
|
|
249
|
-
return [primary, alt];
|
|
250
|
-
}
|
|
251
|
-
_getPaths(options = {}) {
|
|
252
|
-
const [primary, alt] = this._getPersistentPaths(options);
|
|
253
|
-
const tempPath = this._getTempPath();
|
|
254
|
-
return [primary, alt, tempPath];
|
|
255
|
-
}
|
|
256
227
|
/**
|
|
257
228
|
* Helper: Convert Promise-based file system operations to Effection operations
|
|
258
229
|
* This ensures proper structured concurrency and cancellation support
|
|
259
230
|
*/
|
|
231
|
+
/** True when `path` exists; any failure to stat means absent, like `os.path.exists`. */
|
|
260
232
|
*statOp(path) {
|
|
261
|
-
return yield* action((resolve
|
|
262
|
-
dntShim.Deno.stat(path)
|
|
263
|
-
.then(() => resolve(true))
|
|
264
|
-
.catch((error) => {
|
|
265
|
-
if (isNotFoundLike(error)) {
|
|
266
|
-
resolve(false);
|
|
267
|
-
}
|
|
268
|
-
else {
|
|
269
|
-
reject(error);
|
|
270
|
-
}
|
|
271
|
-
});
|
|
233
|
+
return yield* action((resolve) => {
|
|
234
|
+
dntShim.Deno.stat(path).then(() => resolve(true)).catch(() => resolve(false));
|
|
272
235
|
return () => { };
|
|
273
236
|
});
|
|
274
237
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
dntShim.Deno.stat(path)
|
|
280
|
-
.then(() => resolve(true))
|
|
281
|
-
.catch(() => resolve(false));
|
|
282
|
-
return () => { };
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
*mkdirOp(path, perm) {
|
|
286
|
-
return yield* action((resolve, reject) => {
|
|
287
|
-
dntShim.Deno.mkdir(path, { recursive: true, mode: perm })
|
|
288
|
-
.then(() => resolve(true))
|
|
289
|
-
.catch((error) => {
|
|
290
|
-
if (isPermissionDeniedLike(error)) {
|
|
291
|
-
resolve(false);
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
reject(error);
|
|
295
|
-
}
|
|
296
|
-
});
|
|
238
|
+
/** Create a directory and its parents with default permissions, like `os.makedirs`. */
|
|
239
|
+
*mkdirOp(path) {
|
|
240
|
+
yield* action((resolve, reject) => {
|
|
241
|
+
dntShim.Deno.mkdir(path, { recursive: true }).then(() => resolve()).catch(reject);
|
|
297
242
|
return () => { };
|
|
298
243
|
});
|
|
299
244
|
}
|
|
@@ -336,152 +281,93 @@ export class PathManager {
|
|
|
336
281
|
});
|
|
337
282
|
}
|
|
338
283
|
/**
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
* - Tries primary path (/usr/local/var/keri/*) first
|
|
342
|
-
* - Falls back to alt path (~/.tufa/*) on OS errors or access issues
|
|
343
|
-
*
|
|
344
|
-
* Returns Effection Operation with true if path is created and accessible, false otherwise.
|
|
284
|
+
* Close, then open the path, mirroring hio `Filer.reopen`. An existing path
|
|
285
|
+
* is kept only when `reuse` is set; otherwise the path is made again.
|
|
345
286
|
*/
|
|
346
287
|
*reopen(options = {}) {
|
|
347
|
-
this.
|
|
348
|
-
const headDirPath = options.headDirPath ?? this.headDirPath;
|
|
349
|
-
const clean = options.clean || false;
|
|
350
|
-
const reuse = options.reuse || false;
|
|
351
|
-
const clear = options.clear || false;
|
|
352
|
-
const [primary, alt, tempPath] = this._getPaths({
|
|
353
|
-
...options,
|
|
354
|
-
headDirPath,
|
|
355
|
-
clean,
|
|
356
|
-
});
|
|
357
|
-
const resolved = yield* this._resolvePath({
|
|
358
|
-
primary,
|
|
359
|
-
alt,
|
|
360
|
-
tempPath,
|
|
361
|
-
headDirPath,
|
|
362
|
-
reuse,
|
|
363
|
-
});
|
|
364
|
-
this.headDirPath = resolved.headDirPath;
|
|
365
|
-
if (clear) {
|
|
366
|
-
yield* this._clearPath(resolved.path);
|
|
367
|
-
}
|
|
368
|
-
if (!this.filed) {
|
|
369
|
-
yield* this._ensureDirectoryExists(resolved.path);
|
|
370
|
-
}
|
|
371
|
-
this.path = resolved.path;
|
|
372
|
-
this.opened = true;
|
|
373
|
-
return this.opened;
|
|
374
|
-
}
|
|
375
|
-
/** Update instance fields from caller-provided options. */
|
|
376
|
-
_applyOptions(options) {
|
|
288
|
+
yield* this.close(options.clear ?? false);
|
|
377
289
|
this.temp = options.temp ?? this.temp;
|
|
290
|
+
this.headDirPath = options.headDirPath ?? this.headDirPath;
|
|
378
291
|
this.perm = options.perm ?? this.perm;
|
|
379
292
|
this.mode = options.mode ?? this.mode;
|
|
380
293
|
this.fext = options.fext ?? this.fext;
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
* Select which concrete path to use: temp, primary with alt fallback,
|
|
384
|
-
* reuse with alt fallback, or primary directly (custom headDirPath).
|
|
385
|
-
*/
|
|
386
|
-
*_resolvePath(params) {
|
|
387
|
-
if (this.temp) {
|
|
388
|
-
return { path: params.tempPath, headDirPath: params.headDirPath };
|
|
294
|
+
if (!this.path || !options.reuse || !(yield* this.statOp(this.path))) {
|
|
295
|
+
this.path = yield* this.remake(options.clean ?? false);
|
|
389
296
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
}
|
|
393
|
-
return yield* this._createOrFallback(params.primary, params.alt, params.headDirPath);
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
|
-
* Try to use or create the primary path. If creation fails (e.g. EACCES),
|
|
397
|
-
* fall back to the alt path. Throws if alt path also fails.
|
|
398
|
-
*/
|
|
399
|
-
*_createOrFallback(primary, alt, headDirPath) {
|
|
400
|
-
const exists = yield* this.statOp(primary);
|
|
401
|
-
if (exists) {
|
|
402
|
-
return { path: primary, headDirPath };
|
|
403
|
-
}
|
|
404
|
-
this.logger.debug(`Creating directory at ${primary}`);
|
|
405
|
-
const created = yield* this.mkdirOp(primary, this.perm);
|
|
406
|
-
if (created) {
|
|
407
|
-
return { path: primary, headDirPath };
|
|
408
|
-
}
|
|
409
|
-
this.logger.debug(`Failed to create primary path, falling back to alt path`);
|
|
410
|
-
const altReady = yield* this._ensurePathAccessible(alt);
|
|
411
|
-
if (!altReady) {
|
|
412
|
-
this.logger.error(`Alt path not available at ${alt}`);
|
|
413
|
-
throw new PathError(`Alt path not available at ${alt}`);
|
|
414
|
-
}
|
|
415
|
-
return { path: alt, headDirPath: this.defaults.altHeadDirPath };
|
|
297
|
+
this.opened = true;
|
|
298
|
+
return true;
|
|
416
299
|
}
|
|
417
300
|
/**
|
|
418
|
-
*
|
|
419
|
-
*
|
|
301
|
+
* Choose and create the path, mirroring hio `Filer.remake`. `headDirPath` is
|
|
302
|
+
* left alone on fallback, so each open retries the primary location first.
|
|
420
303
|
*/
|
|
421
|
-
*
|
|
422
|
-
const
|
|
423
|
-
const
|
|
424
|
-
if (
|
|
425
|
-
|
|
304
|
+
*remake(clean) {
|
|
305
|
+
const tail = clean ? this.defaults.cleanTailDirPath : this.defaults.tailDirPath;
|
|
306
|
+
const name = this.fileName();
|
|
307
|
+
if (this.temp) {
|
|
308
|
+
this.tempRoot = join(tempHeadDir(), `${this.defaults.tempPrefix}${this.name}${this.defaults.tempSuffix}`);
|
|
309
|
+
const path = this.filed || this.extensioned ? join(this.tempRoot, name) : this.tempRoot;
|
|
310
|
+
yield* this.makePath(path);
|
|
311
|
+
return path;
|
|
426
312
|
}
|
|
427
|
-
this.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
313
|
+
let path = resolve(this._pathExpandTilde(join(this.headDirPath, tail, this.base, name)));
|
|
314
|
+
if (clean && (yield* this.statOp(path)))
|
|
315
|
+
yield* this.rmOp(path);
|
|
316
|
+
if (!(yield* this.statOp(path))) {
|
|
317
|
+
try {
|
|
318
|
+
yield* this.makePath(path);
|
|
319
|
+
}
|
|
320
|
+
catch (cause) {
|
|
321
|
+
this.logger.debug(`Failed to create ${path}, falling back to alt path`);
|
|
322
|
+
path = yield* this.makeAltPath(clean, name, cause);
|
|
323
|
+
}
|
|
431
324
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (!altReady) {
|
|
435
|
-
this.logger.debug(`Alt path not available: ${alt}`);
|
|
325
|
+
else if (!isAccessible(path)) {
|
|
326
|
+
path = yield* this.makeAltPath(clean, name);
|
|
436
327
|
}
|
|
437
|
-
|
|
328
|
+
if (!this.extensioned && dntShim.Deno.build.os !== "windows")
|
|
329
|
+
dntShim.Deno.chmodSync(path, this.perm);
|
|
330
|
+
return path;
|
|
438
331
|
}
|
|
439
|
-
/**
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
*/
|
|
443
|
-
*_ensurePathAccessible(path) {
|
|
444
|
-
const exists = yield* this.statOp(path);
|
|
445
|
-
if (!exists) {
|
|
446
|
-
this.logger.debug(`Creating directory at ${path}`);
|
|
447
|
-
return yield* this.mkdirOp(path, this.perm);
|
|
448
|
-
}
|
|
449
|
-
return yield* this.accessOp(path);
|
|
332
|
+
/** Name the path uses, with `fext` added to an extensionless file name. */
|
|
333
|
+
fileName() {
|
|
334
|
+
return (this.filed || this.extensioned) && !extname(this.name) ? `${this.name}.${this.fext}` : this.name;
|
|
450
335
|
}
|
|
451
|
-
/**
|
|
452
|
-
*
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
336
|
+
/** Create a directory path, or a file path's parents and the file when `filed`. */
|
|
337
|
+
*makePath(path) {
|
|
338
|
+
if (!this.filed && !this.extensioned) {
|
|
339
|
+
yield* this.mkdirOp(path);
|
|
340
|
+
return;
|
|
456
341
|
}
|
|
342
|
+
yield* this.mkdirOp(dirname(path));
|
|
343
|
+
if (this.filed)
|
|
344
|
+
dntShim.Deno.openSync(path, { read: true, write: true, create: true, mode: this.perm }).close();
|
|
457
345
|
}
|
|
458
|
-
/**
|
|
459
|
-
*
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
this.logger.debug(`Failed to create directory at ${path}`);
|
|
466
|
-
}
|
|
346
|
+
/** Make the home-directory alternate, failing when it is unavailable too. */
|
|
347
|
+
*makeAltPath(clean, name, cause) {
|
|
348
|
+
const tail = clean ? this.defaults.altCleanTailDirPath : this.defaults.altTailDirPath;
|
|
349
|
+
const path = resolve(this._pathExpandTilde(this.defaults.altHeadDirPath), tail, this.base, name);
|
|
350
|
+
try {
|
|
351
|
+
if (!(yield* this.statOp(path)))
|
|
352
|
+
yield* this.makePath(path);
|
|
467
353
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
this.logger.debug(`Path exists but is not accessible: ${path}`);
|
|
472
|
-
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
this.logger.error(`Alt path not available at ${path}`);
|
|
356
|
+
throw new PathError(`Alt path not available at ${path}`, { cause: cause ?? error });
|
|
473
357
|
}
|
|
358
|
+
return path;
|
|
474
359
|
}
|
|
475
360
|
/**
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
* Uses Effection for structured concurrency
|
|
361
|
+
* Mark closed, removing the path when `clear` is set. The path is retained so
|
|
362
|
+
* a later `reopen({ reuse: true })` finds it, as hio does.
|
|
479
363
|
*/
|
|
480
364
|
*close(clear = false) {
|
|
481
365
|
if (clear && this.path) {
|
|
482
366
|
yield* this.rmOp(this.path);
|
|
367
|
+
if (this.tempRoot)
|
|
368
|
+
yield* this.rmOp(this.tempRoot);
|
|
369
|
+
this.tempRoot = null;
|
|
483
370
|
}
|
|
484
|
-
this.path = null;
|
|
485
371
|
this.opened = false;
|
|
486
372
|
return true;
|
|
487
373
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composition seam between typed domain stores and a `DBer` backend.
|
|
3
|
+
*
|
|
4
|
+
* ADR-0015 owns the store contract. A `StoreOwner` is a domain store such as
|
|
5
|
+
* `Noter` or `Reger`: it borrows no backend knowledge and delegates lifecycle
|
|
6
|
+
* and transactions to the one store it composes over.
|
|
7
|
+
*/
|
|
8
|
+
import { DatabaseNotOpenError } from "../../core/errors.js";
|
|
9
|
+
/** A domain store composed over one `DBer`. */
|
|
10
|
+
export class StoreOwner {
|
|
11
|
+
constructor(store) {
|
|
12
|
+
Object.defineProperty(this, "store", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: store
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
get name() {
|
|
20
|
+
return this.store.name;
|
|
21
|
+
}
|
|
22
|
+
get base() {
|
|
23
|
+
return this.store.base;
|
|
24
|
+
}
|
|
25
|
+
get opened() {
|
|
26
|
+
return this.store.opened;
|
|
27
|
+
}
|
|
28
|
+
get readonly() {
|
|
29
|
+
return this.store.readonly;
|
|
30
|
+
}
|
|
31
|
+
get temp() {
|
|
32
|
+
return this.store.temp;
|
|
33
|
+
}
|
|
34
|
+
get inWriteTransaction() {
|
|
35
|
+
return this.store.inWriteTransaction;
|
|
36
|
+
}
|
|
37
|
+
/** Filesystem path on an LMDB-backed store; `null` elsewhere. */
|
|
38
|
+
get path() {
|
|
39
|
+
return this.store.path ?? null;
|
|
40
|
+
}
|
|
41
|
+
/** Native LMDB environment for low-level tests only; `null` on other backends. */
|
|
42
|
+
get env() {
|
|
43
|
+
return this.store.env ?? null;
|
|
44
|
+
}
|
|
45
|
+
get writeVersion() {
|
|
46
|
+
return this.store.writeVersion;
|
|
47
|
+
}
|
|
48
|
+
transaction(fn) {
|
|
49
|
+
return this.store.transaction(fn);
|
|
50
|
+
}
|
|
51
|
+
flushed() {
|
|
52
|
+
return this.store.flushed();
|
|
53
|
+
}
|
|
54
|
+
refreshRead() {
|
|
55
|
+
this.store.refreshRead();
|
|
56
|
+
}
|
|
57
|
+
hasTable(name) {
|
|
58
|
+
return this.store.hasTable(name);
|
|
59
|
+
}
|
|
60
|
+
getVer() {
|
|
61
|
+
return this.store.getVer();
|
|
62
|
+
}
|
|
63
|
+
setVer(val) {
|
|
64
|
+
this.store.setVer(val);
|
|
65
|
+
}
|
|
66
|
+
close(clear = false) {
|
|
67
|
+
return this.store.close(clear);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Open a ready owner for its caller, closing an unreturned acquisition on
|
|
72
|
+
* failure or cancellation without masking the original error.
|
|
73
|
+
*/
|
|
74
|
+
export function* openOwner(owner, label, options) {
|
|
75
|
+
let delivered = false;
|
|
76
|
+
let failure;
|
|
77
|
+
try {
|
|
78
|
+
if (!(yield* owner.reopen(options)))
|
|
79
|
+
throw new DatabaseNotOpenError(`Failed to open ${label}`);
|
|
80
|
+
delivered = true;
|
|
81
|
+
return owner;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
failure = { error };
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
if (!delivered) {
|
|
89
|
+
try {
|
|
90
|
+
yield* owner.close();
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (failure) {
|
|
94
|
+
// deno-lint-ignore no-unsafe-finally -- Preserve the operation failure alongside shutdown failure.
|
|
95
|
+
throw new AggregateError([failure.error, error], "Database acquisition and close failed", {
|
|
96
|
+
cause: failure.error,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// deno-lint-ignore no-unsafe-finally -- A cancelled acquisition still reports its close failure.
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|