@bcts/hubert 1.0.0-alpha.17
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 +48 -0
- package/README.md +18 -0
- package/dist/arid-derivation-1CJuU-kZ.cjs +150 -0
- package/dist/arid-derivation-1CJuU-kZ.cjs.map +1 -0
- package/dist/arid-derivation-CbqACjdg.mjs +126 -0
- package/dist/arid-derivation-CbqACjdg.mjs.map +1 -0
- package/dist/bin/hubert.cjs +384 -0
- package/dist/bin/hubert.cjs.map +1 -0
- package/dist/bin/hubert.d.cts +1 -0
- package/dist/bin/hubert.d.mts +1 -0
- package/dist/bin/hubert.mjs +383 -0
- package/dist/bin/hubert.mjs.map +1 -0
- package/dist/chunk-CbDLau6x.cjs +34 -0
- package/dist/hybrid/index.cjs +14 -0
- package/dist/hybrid/index.d.cts +3 -0
- package/dist/hybrid/index.d.mts +3 -0
- package/dist/hybrid/index.mjs +6 -0
- package/dist/hybrid-BZhumygj.mjs +356 -0
- package/dist/hybrid-BZhumygj.mjs.map +1 -0
- package/dist/hybrid-dX5JLumO.cjs +410 -0
- package/dist/hybrid-dX5JLumO.cjs.map +1 -0
- package/dist/index-BEzpUC7r.d.mts +380 -0
- package/dist/index-BEzpUC7r.d.mts.map +1 -0
- package/dist/index-C2F6ugLL.d.mts +210 -0
- package/dist/index-C2F6ugLL.d.mts.map +1 -0
- package/dist/index-CUnDouMb.d.mts +215 -0
- package/dist/index-CUnDouMb.d.mts.map +1 -0
- package/dist/index-CV6lZJqY.d.cts +380 -0
- package/dist/index-CV6lZJqY.d.cts.map +1 -0
- package/dist/index-CY3TCzIm.d.cts +217 -0
- package/dist/index-CY3TCzIm.d.cts.map +1 -0
- package/dist/index-DEr4SR1J.d.cts +215 -0
- package/dist/index-DEr4SR1J.d.cts.map +1 -0
- package/dist/index-T1LHanIb.d.mts +217 -0
- package/dist/index-T1LHanIb.d.mts.map +1 -0
- package/dist/index-jyzuOhFB.d.cts +210 -0
- package/dist/index-jyzuOhFB.d.cts.map +1 -0
- package/dist/index.cjs +60 -0
- package/dist/index.d.cts +161 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +161 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +10 -0
- package/dist/ipfs/index.cjs +13 -0
- package/dist/ipfs/index.d.cts +3 -0
- package/dist/ipfs/index.d.mts +3 -0
- package/dist/ipfs/index.mjs +5 -0
- package/dist/ipfs-BRMMCBjv.mjs +1 -0
- package/dist/ipfs-CetOVQcO.cjs +0 -0
- package/dist/kv-BAmhmMOo.cjs +425 -0
- package/dist/kv-BAmhmMOo.cjs.map +1 -0
- package/dist/kv-C-emxv0w.mjs +375 -0
- package/dist/kv-C-emxv0w.mjs.map +1 -0
- package/dist/kv-DJiKvypY.mjs +403 -0
- package/dist/kv-DJiKvypY.mjs.map +1 -0
- package/dist/kv-store-DmngWWuw.d.mts +183 -0
- package/dist/kv-store-DmngWWuw.d.mts.map +1 -0
- package/dist/kv-store-ww-AUyLd.d.cts +183 -0
- package/dist/kv-store-ww-AUyLd.d.cts.map +1 -0
- package/dist/kv-yjvQa_LH.cjs +457 -0
- package/dist/kv-yjvQa_LH.cjs.map +1 -0
- package/dist/logging-hmzNzifq.mjs +158 -0
- package/dist/logging-hmzNzifq.mjs.map +1 -0
- package/dist/logging-qc9uMgil.cjs +212 -0
- package/dist/logging-qc9uMgil.cjs.map +1 -0
- package/dist/mainline/index.cjs +12 -0
- package/dist/mainline/index.d.cts +3 -0
- package/dist/mainline/index.d.mts +3 -0
- package/dist/mainline/index.mjs +5 -0
- package/dist/mainline-D_jfeFMh.cjs +0 -0
- package/dist/mainline-cFIuXbo-.mjs +1 -0
- package/dist/server/index.cjs +14 -0
- package/dist/server/index.d.cts +3 -0
- package/dist/server/index.d.mts +3 -0
- package/dist/server/index.mjs +3 -0
- package/dist/server-BBNRZ30D.cjs +912 -0
- package/dist/server-BBNRZ30D.cjs.map +1 -0
- package/dist/server-DVyk9gqU.mjs +836 -0
- package/dist/server-DVyk9gqU.mjs.map +1 -0
- package/package.json +125 -0
- package/src/arid-derivation.ts +155 -0
- package/src/bin/hubert.ts +667 -0
- package/src/error.ts +89 -0
- package/src/hybrid/error.ts +77 -0
- package/src/hybrid/index.ts +24 -0
- package/src/hybrid/kv.ts +236 -0
- package/src/hybrid/reference.ts +176 -0
- package/src/index.ts +145 -0
- package/src/ipfs/error.ts +83 -0
- package/src/ipfs/index.ts +24 -0
- package/src/ipfs/kv.ts +476 -0
- package/src/ipfs/value.ts +85 -0
- package/src/kv-store.ts +128 -0
- package/src/logging.ts +88 -0
- package/src/mainline/error.ts +108 -0
- package/src/mainline/index.ts +23 -0
- package/src/mainline/kv.ts +411 -0
- package/src/server/error.ts +83 -0
- package/src/server/index.ts +29 -0
- package/src/server/kv.ts +211 -0
- package/src/server/memory-kv.ts +191 -0
- package/src/server/server-kv.ts +92 -0
- package/src/server/server.ts +369 -0
- package/src/server/sqlite-kv.ts +295 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_chunk = require('../chunk-CbDLau6x.cjs');
|
|
3
|
+
const require_logging = require('../logging-qc9uMgil.cjs');
|
|
4
|
+
require('../arid-derivation-1CJuU-kZ.cjs');
|
|
5
|
+
const require_server = require('../server-BBNRZ30D.cjs');
|
|
6
|
+
const require_kv = require('../kv-yjvQa_LH.cjs');
|
|
7
|
+
require('../ipfs-CetOVQcO.cjs');
|
|
8
|
+
const require_kv$1 = require('../kv-BAmhmMOo.cjs');
|
|
9
|
+
require('../mainline-D_jfeFMh.cjs');
|
|
10
|
+
const require_hybrid = require('../hybrid-dX5JLumO.cjs');
|
|
11
|
+
require('../index.cjs');
|
|
12
|
+
let path = require("path");
|
|
13
|
+
path = require_chunk.__toESM(path);
|
|
14
|
+
let _bcts_components = require("@bcts/components");
|
|
15
|
+
let _bcts_envelope = require("@bcts/envelope");
|
|
16
|
+
let commander = require("commander");
|
|
17
|
+
let _bcts_rand = require("@bcts/rand");
|
|
18
|
+
|
|
19
|
+
//#region src/bin/hubert.ts
|
|
20
|
+
/**
|
|
21
|
+
* Hubert: Secure Distributed Substrate for Multiparty Transactions
|
|
22
|
+
*
|
|
23
|
+
* A command-line tool for storing and retrieving Gordian Envelopes using
|
|
24
|
+
* distributed storage backends (BitTorrent Mainline DHT or IPFS).
|
|
25
|
+
*
|
|
26
|
+
* Port of bin/hubert.rs from hubert-rust.
|
|
27
|
+
*
|
|
28
|
+
* @module
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Parse an ARID from ur:arid string format.
|
|
32
|
+
*
|
|
33
|
+
* Port of `parse_arid()` from bin/hubert.rs lines 150-153.
|
|
34
|
+
*/
|
|
35
|
+
function parseArid(s) {
|
|
36
|
+
try {
|
|
37
|
+
return _bcts_components.ARID.fromUrString(s);
|
|
38
|
+
} catch {
|
|
39
|
+
throw new Error("Invalid ARID format. Expected ur:arid");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse an Envelope from ur:envelope string format.
|
|
44
|
+
*
|
|
45
|
+
* Port of `parse_envelope()` from bin/hubert.rs lines 155-161.
|
|
46
|
+
*/
|
|
47
|
+
function parseEnvelope(s) {
|
|
48
|
+
try {
|
|
49
|
+
return _bcts_envelope.Envelope.fromUrString(s);
|
|
50
|
+
} catch {
|
|
51
|
+
throw new Error("Invalid envelope format. Expected ur:envelope");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Generate a random envelope with the specified size.
|
|
56
|
+
*
|
|
57
|
+
* Port of `generate_random_envelope()` from bin/hubert.rs lines 163-167.
|
|
58
|
+
*/
|
|
59
|
+
function generateRandomEnvelope(size) {
|
|
60
|
+
const randomBytes = (0, _bcts_rand.randomData)(size);
|
|
61
|
+
return _bcts_envelope.Envelope.new(randomBytes);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if Mainline DHT is available.
|
|
65
|
+
*
|
|
66
|
+
* Port of `check_mainline()` from bin/hubert.rs lines 169-182.
|
|
67
|
+
*/
|
|
68
|
+
async function checkMainline() {
|
|
69
|
+
try {
|
|
70
|
+
await (await require_kv$1.MainlineDhtKv.create()).destroy();
|
|
71
|
+
console.log("✓ Mainline DHT is available");
|
|
72
|
+
} catch (e) {
|
|
73
|
+
throw new Error(`✗ Mainline DHT is not available: ${e instanceof Error ? e.message : e}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if IPFS is available.
|
|
78
|
+
*
|
|
79
|
+
* Port of `check_ipfs()` from bin/hubert.rs lines 184-205.
|
|
80
|
+
*/
|
|
81
|
+
async function checkIpfs(port) {
|
|
82
|
+
try {
|
|
83
|
+
const url = `http://127.0.0.1:${port}/api/v0/version`;
|
|
84
|
+
const controller = new AbortController();
|
|
85
|
+
const timeout = setTimeout(() => controller.abort(), 2e3);
|
|
86
|
+
const response = await fetch(url, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
signal: controller.signal
|
|
89
|
+
});
|
|
90
|
+
clearTimeout(timeout);
|
|
91
|
+
if (response.ok) console.log(`✓ IPFS is available at 127.0.0.1:${port}`);
|
|
92
|
+
else throw new Error(`✗ IPFS daemon returned error: ${response.status}`);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: connection timeout`);
|
|
95
|
+
throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if Hubert server is available.
|
|
100
|
+
*/
|
|
101
|
+
async function checkServer(host, port) {
|
|
102
|
+
try {
|
|
103
|
+
const url = `http://${host}:${port}/health`;
|
|
104
|
+
const controller = new AbortController();
|
|
105
|
+
const timeout = setTimeout(() => controller.abort(), 2e3);
|
|
106
|
+
const response = await fetch(url, {
|
|
107
|
+
method: "GET",
|
|
108
|
+
signal: controller.signal
|
|
109
|
+
});
|
|
110
|
+
clearTimeout(timeout);
|
|
111
|
+
if (response.ok) {
|
|
112
|
+
const json = await response.json();
|
|
113
|
+
if (json.server === "hubert") {
|
|
114
|
+
const version = json.version ?? "unknown";
|
|
115
|
+
console.log(`✓ Hubert server is available at ${host}:${port} (version ${version})`);
|
|
116
|
+
} else throw new Error(`✗ Server at ${host}:${port} is not a Hubert server`);
|
|
117
|
+
} else throw new Error(`✗ Server at ${host}:${port} is not available (status: ${response.status})`);
|
|
118
|
+
} catch (e) {
|
|
119
|
+
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ Server is not available at ${host}:${port}: connection timeout`);
|
|
120
|
+
throw new Error(`✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Put envelope to Mainline DHT.
|
|
125
|
+
*
|
|
126
|
+
* Port of `put_mainline()` from bin/hubert.rs lines 207-221.
|
|
127
|
+
*/
|
|
128
|
+
async function putMainline(arid, envelope, verbose) {
|
|
129
|
+
const store = await require_kv$1.MainlineDhtKv.create();
|
|
130
|
+
try {
|
|
131
|
+
await store.put(arid, envelope, void 0, verbose);
|
|
132
|
+
if (verbose) require_logging.verbosePrintln("✓ Stored envelope at ARID");
|
|
133
|
+
} finally {
|
|
134
|
+
await store.destroy();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Put envelope to IPFS.
|
|
139
|
+
*
|
|
140
|
+
* Port of `put_ipfs()` from bin/hubert.rs lines 223-250.
|
|
141
|
+
*/
|
|
142
|
+
async function putIpfs(arid, envelope, port, pin, verbose) {
|
|
143
|
+
const result = await new require_kv.IpfsKv(`http://127.0.0.1:${port}`).withPinContent(pin).put(arid, envelope, void 0, verbose);
|
|
144
|
+
if (verbose) require_logging.verbosePrintln("✓ Stored envelope at ARID");
|
|
145
|
+
if (pin) {
|
|
146
|
+
const cidPart = result.split("ipfs://")[1];
|
|
147
|
+
if (cidPart) console.log(`CID: ${cidPart}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Put envelope to Hybrid storage.
|
|
152
|
+
*
|
|
153
|
+
* Port of `put_hybrid()` from bin/hubert.rs lines 278-308.
|
|
154
|
+
*/
|
|
155
|
+
async function putHybrid(arid, envelope, port, pin, verbose) {
|
|
156
|
+
const url = `http://127.0.0.1:${port}`;
|
|
157
|
+
const store = (await require_hybrid.HybridKv.create(url)).withPinContent(pin);
|
|
158
|
+
try {
|
|
159
|
+
const result = await store.put(arid, envelope, void 0, verbose);
|
|
160
|
+
if (verbose) require_logging.verbosePrintln("✓ Stored envelope at ARID");
|
|
161
|
+
if (pin && result.includes("ipfs://")) {
|
|
162
|
+
const cidPart = result.split("ipfs://")[1];
|
|
163
|
+
if (cidPart) console.log(`CID: ${cidPart}`);
|
|
164
|
+
}
|
|
165
|
+
} finally {
|
|
166
|
+
await store.destroy();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Put envelope to Hubert server.
|
|
171
|
+
*
|
|
172
|
+
* Port of `put_server()` from bin/hubert.rs lines 324-344.
|
|
173
|
+
*/
|
|
174
|
+
async function putServer(host, port, arid, envelope, ttl, verbose) {
|
|
175
|
+
await new require_server.ServerKvClient(`http://${host}:${port}`).put(arid, envelope, ttl, verbose);
|
|
176
|
+
if (verbose) require_logging.verbosePrintln("✓ Stored envelope at ARID");
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get envelope from Mainline DHT.
|
|
180
|
+
*
|
|
181
|
+
* Port of `get_mainline()` from bin/hubert.rs lines 252-262.
|
|
182
|
+
*/
|
|
183
|
+
async function getMainline(arid, timeout, verbose) {
|
|
184
|
+
const store = await require_kv$1.MainlineDhtKv.create();
|
|
185
|
+
try {
|
|
186
|
+
return await store.get(arid, timeout, verbose);
|
|
187
|
+
} finally {
|
|
188
|
+
await store.destroy();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get envelope from IPFS.
|
|
193
|
+
*
|
|
194
|
+
* Port of `get_ipfs()` from bin/hubert.rs lines 264-276.
|
|
195
|
+
*/
|
|
196
|
+
async function getIpfs(arid, timeout, port, verbose) {
|
|
197
|
+
return await new require_kv.IpfsKv(`http://127.0.0.1:${port}`).get(arid, timeout, verbose);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Get envelope from Hybrid storage.
|
|
201
|
+
*
|
|
202
|
+
* Port of `get_hybrid()` from bin/hubert.rs lines 310-322.
|
|
203
|
+
*/
|
|
204
|
+
async function getHybrid(arid, timeout, port, verbose) {
|
|
205
|
+
const url = `http://127.0.0.1:${port}`;
|
|
206
|
+
const store = await require_hybrid.HybridKv.create(url);
|
|
207
|
+
try {
|
|
208
|
+
return await store.get(arid, timeout, verbose);
|
|
209
|
+
} finally {
|
|
210
|
+
await store.destroy();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get envelope from Hubert server.
|
|
215
|
+
*
|
|
216
|
+
* Port of `get_server()` from bin/hubert.rs lines 346-361.
|
|
217
|
+
*/
|
|
218
|
+
async function getServer(host, port, arid, timeout, verbose) {
|
|
219
|
+
return await new require_server.ServerKvClient(`http://${host}:${port}`).get(arid, timeout, verbose);
|
|
220
|
+
}
|
|
221
|
+
const program = new commander.Command();
|
|
222
|
+
program.name("hubert").description("Distributed substrate for multiparty transactions").version("1.0.0-alpha.1").option("-v, --verbose", "Enable verbose logging", false);
|
|
223
|
+
const generateCmd = program.command("generate").description("Generate a new ARID or example Envelope");
|
|
224
|
+
generateCmd.command("arid").description("Generate a new ARID").action(() => {
|
|
225
|
+
const arid = _bcts_components.ARID.new();
|
|
226
|
+
console.log(arid.urString());
|
|
227
|
+
});
|
|
228
|
+
generateCmd.command("envelope <size>").description("Generate a test envelope with random data").action((sizeStr) => {
|
|
229
|
+
const size = parseInt(sizeStr, 10);
|
|
230
|
+
if (isNaN(size) || size < 0) {
|
|
231
|
+
console.error("Size must be a positive integer");
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
const envelope = generateRandomEnvelope(size);
|
|
235
|
+
console.log(envelope.urString());
|
|
236
|
+
});
|
|
237
|
+
program.command("put <arid> <envelope>").description("Store an envelope at an ARID").option("-s, --storage <backend>", "Storage backend to use", "mainline").option("--host <host>", "Server host (for --storage server)").option("--port <port>", "Port (for --storage server/ipfs/hybrid)").option("--ttl <seconds>", "Time-to-live in seconds (for --storage server)").option("--pin", "Pin content in IPFS (only for --storage ipfs or --storage hybrid)", false).action(async (aridStr, envelopeStr, options) => {
|
|
238
|
+
const verbose = program.opts()["verbose"];
|
|
239
|
+
const storage = options.storage;
|
|
240
|
+
const port = options.port ? parseInt(options.port, 10) : void 0;
|
|
241
|
+
const ttl = options.ttl ? parseInt(options.ttl, 10) : void 0;
|
|
242
|
+
try {
|
|
243
|
+
if (storage === "mainline") {
|
|
244
|
+
if (port !== void 0) throw new Error("--port option is not supported for --storage mainline");
|
|
245
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage mainline");
|
|
246
|
+
if (ttl !== void 0) throw new Error("--ttl option is only supported for --storage server");
|
|
247
|
+
if (options.pin) throw new Error("--pin option is only supported for --storage ipfs or --storage hybrid");
|
|
248
|
+
} else if (storage === "ipfs") {
|
|
249
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage ipfs (always uses 127.0.0.1)");
|
|
250
|
+
if (ttl !== void 0) throw new Error("--ttl option is only supported for --storage server");
|
|
251
|
+
} else if (storage === "hybrid") {
|
|
252
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage hybrid (always uses 127.0.0.1)");
|
|
253
|
+
if (ttl !== void 0) throw new Error("--ttl option is only supported for --storage server");
|
|
254
|
+
} else if (storage === "server") {
|
|
255
|
+
if (options.pin) throw new Error("--pin option is only supported for --storage ipfs or --storage hybrid");
|
|
256
|
+
}
|
|
257
|
+
const arid = parseArid(aridStr);
|
|
258
|
+
const envelope = parseEnvelope(envelopeStr);
|
|
259
|
+
switch (storage) {
|
|
260
|
+
case "mainline":
|
|
261
|
+
await putMainline(arid, envelope, verbose);
|
|
262
|
+
console.log("Stored in Mainline DHT");
|
|
263
|
+
break;
|
|
264
|
+
case "ipfs":
|
|
265
|
+
await putIpfs(arid, envelope, port ?? 5001, options.pin, verbose);
|
|
266
|
+
console.log("Stored in IPFS");
|
|
267
|
+
break;
|
|
268
|
+
case "hybrid":
|
|
269
|
+
await putHybrid(arid, envelope, port ?? 5001, options.pin, verbose);
|
|
270
|
+
console.log("Stored in Hybrid storage");
|
|
271
|
+
break;
|
|
272
|
+
case "server":
|
|
273
|
+
await putServer(options.host ?? "127.0.0.1", port ?? 45678, arid, envelope, ttl, verbose);
|
|
274
|
+
console.log("Stored in server");
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
} catch (e) {
|
|
278
|
+
console.error(e instanceof Error ? e.message : e);
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
program.command("get <arid>").description("Retrieve an envelope by ARID").option("-s, --storage <backend>", "Storage backend to use", "mainline").option("--host <host>", "Server host (for --storage server)").option("--port <port>", "Port (for --storage server/ipfs/hybrid)").option("-t, --timeout <seconds>", "Maximum time to wait in seconds", "30").action(async (aridStr, options) => {
|
|
283
|
+
const verbose = program.opts()["verbose"];
|
|
284
|
+
const storage = options.storage;
|
|
285
|
+
const port = options.port ? parseInt(options.port, 10) : void 0;
|
|
286
|
+
const timeout = parseInt(options.timeout, 10);
|
|
287
|
+
try {
|
|
288
|
+
if (storage === "mainline") {
|
|
289
|
+
if (port !== void 0) throw new Error("--port option is not supported for --storage mainline");
|
|
290
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage mainline");
|
|
291
|
+
} else if (storage === "ipfs") {
|
|
292
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage ipfs (always uses 127.0.0.1)");
|
|
293
|
+
} else if (storage === "hybrid") {
|
|
294
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage hybrid (always uses 127.0.0.1)");
|
|
295
|
+
}
|
|
296
|
+
const arid = parseArid(aridStr);
|
|
297
|
+
let envelope;
|
|
298
|
+
switch (storage) {
|
|
299
|
+
case "mainline":
|
|
300
|
+
envelope = await getMainline(arid, timeout, verbose);
|
|
301
|
+
break;
|
|
302
|
+
case "ipfs":
|
|
303
|
+
envelope = await getIpfs(arid, timeout, port ?? 5001, verbose);
|
|
304
|
+
break;
|
|
305
|
+
case "hybrid":
|
|
306
|
+
envelope = await getHybrid(arid, timeout, port ?? 5001, verbose);
|
|
307
|
+
break;
|
|
308
|
+
case "server":
|
|
309
|
+
envelope = await getServer(options.host ?? "127.0.0.1", port ?? 45678, arid, timeout, verbose);
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
if (envelope) console.log(envelope.urString());
|
|
313
|
+
else throw new Error(`Value not found within ${timeout} seconds`);
|
|
314
|
+
} catch (e) {
|
|
315
|
+
console.error(e instanceof Error ? e.message : e);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
program.command("check").description("Check if storage backend is available").option("-s, --storage <backend>", "Storage backend to use", "mainline").option("--host <host>", "Server host (for --storage server)").option("--port <port>", "Port (for --storage server/ipfs/hybrid)").action(async (options) => {
|
|
320
|
+
const storage = options.storage;
|
|
321
|
+
const port = options.port ? parseInt(options.port, 10) : void 0;
|
|
322
|
+
try {
|
|
323
|
+
if (storage === "mainline") {
|
|
324
|
+
if (port !== void 0) throw new Error("--port option is not supported for --storage mainline");
|
|
325
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage mainline");
|
|
326
|
+
} else if (storage === "ipfs") {
|
|
327
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage ipfs (always uses 127.0.0.1)");
|
|
328
|
+
} else if (storage === "hybrid") {
|
|
329
|
+
if (options.host !== void 0) throw new Error("--host option is not supported for --storage hybrid (always uses 127.0.0.1)");
|
|
330
|
+
}
|
|
331
|
+
switch (storage) {
|
|
332
|
+
case "mainline":
|
|
333
|
+
await checkMainline();
|
|
334
|
+
break;
|
|
335
|
+
case "ipfs":
|
|
336
|
+
await checkIpfs(port ?? 5001);
|
|
337
|
+
break;
|
|
338
|
+
case "hybrid":
|
|
339
|
+
await checkMainline();
|
|
340
|
+
await checkIpfs(port ?? 5001);
|
|
341
|
+
console.log("✓ Hybrid storage is available (DHT + IPFS)");
|
|
342
|
+
break;
|
|
343
|
+
case "server":
|
|
344
|
+
await checkServer(options.host ?? "127.0.0.1", port ?? 45678);
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
} catch (e) {
|
|
348
|
+
console.error(e instanceof Error ? e.message : e);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
program.command("server").description("Start the Hubert HTTP server").option("--port <port>", "Port for the server to listen on", "45678").option("--sqlite <path>", "SQLite database file path for persistent storage").action(async (options) => {
|
|
353
|
+
const verbose = program.opts()["verbose"];
|
|
354
|
+
const port = parseInt(options.port, 10);
|
|
355
|
+
try {
|
|
356
|
+
const config = {
|
|
357
|
+
port,
|
|
358
|
+
maxTtl: 86400,
|
|
359
|
+
verbose
|
|
360
|
+
};
|
|
361
|
+
if (options.sqlite) {
|
|
362
|
+
let sqlitePath = options.sqlite;
|
|
363
|
+
const fs = await import("fs");
|
|
364
|
+
try {
|
|
365
|
+
if (fs.statSync(sqlitePath).isDirectory()) sqlitePath = path.default.join(sqlitePath, "hubert.sqlite");
|
|
366
|
+
} catch {}
|
|
367
|
+
const store = new require_server.SqliteKv(sqlitePath);
|
|
368
|
+
const server = require_server.Server.newSqlite(config, store);
|
|
369
|
+
console.log(`Starting Hubert server on port ${port} with SQLite storage: ${sqlitePath}`);
|
|
370
|
+
await server.run();
|
|
371
|
+
} else {
|
|
372
|
+
const server = require_server.Server.newMemory(config);
|
|
373
|
+
console.log(`Starting Hubert server on port ${port} with in-memory storage`);
|
|
374
|
+
await server.run();
|
|
375
|
+
}
|
|
376
|
+
} catch (e) {
|
|
377
|
+
console.error(e instanceof Error ? e.message : e);
|
|
378
|
+
process.exit(1);
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
program.parse();
|
|
382
|
+
|
|
383
|
+
//#endregion
|
|
384
|
+
//# sourceMappingURL=hubert.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hubert.cjs","names":["ARID","Envelope","MainlineDhtKv","IpfsKv","HybridKv","ServerKvClient","Command","SqliteKv","Server"],"sources":["../../src/bin/hubert.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Hubert: Secure Distributed Substrate for Multiparty Transactions\n *\n * A command-line tool for storing and retrieving Gordian Envelopes using\n * distributed storage backends (BitTorrent Mainline DHT or IPFS).\n *\n * Port of bin/hubert.rs from hubert-rust.\n *\n * @module\n */\n\nimport { Command } from \"commander\";\nimport path from \"path\";\n\nimport { ARID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { randomData } from \"@bcts/rand\";\n\nimport {\n verbosePrintln,\n IpfsKv,\n MainlineDhtKv,\n HybridKv,\n Server,\n type ServerConfig,\n ServerKvClient,\n SqliteKv,\n} from \"../index.js\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\ntype StorageBackend = \"mainline\" | \"ipfs\" | \"hybrid\" | \"server\";\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Parse an ARID from ur:arid string format.\n *\n * Port of `parse_arid()` from bin/hubert.rs lines 150-153.\n */\nfunction parseArid(s: string): ARID {\n try {\n return ARID.fromUrString(s);\n } catch {\n throw new Error(\"Invalid ARID format. Expected ur:arid\");\n }\n}\n\n/**\n * Parse an Envelope from ur:envelope string format.\n *\n * Port of `parse_envelope()` from bin/hubert.rs lines 155-161.\n */\nfunction parseEnvelope(s: string): Envelope {\n try {\n return Envelope.fromUrString(s);\n } catch {\n throw new Error(\"Invalid envelope format. Expected ur:envelope\");\n }\n}\n\n/**\n * Generate a random envelope with the specified size.\n *\n * Port of `generate_random_envelope()` from bin/hubert.rs lines 163-167.\n */\nfunction generateRandomEnvelope(size: number): Envelope {\n const randomBytes = randomData(size);\n // Pass raw Uint8Array directly - Envelope.new accepts it as EnvelopeEncodableValue\n return Envelope.new(randomBytes);\n}\n\n// =============================================================================\n// Check Functions\n// =============================================================================\n\n/**\n * Check if Mainline DHT is available.\n *\n * Port of `check_mainline()` from bin/hubert.rs lines 169-182.\n */\nasync function checkMainline(): Promise<void> {\n try {\n const dht = await MainlineDhtKv.create();\n await dht.destroy();\n console.log(\"✓ Mainline DHT is available\");\n } catch (e) {\n throw new Error(`✗ Mainline DHT is not available: ${e instanceof Error ? e.message : e}`);\n }\n}\n\n/**\n * Check if IPFS is available.\n *\n * Port of `check_ipfs()` from bin/hubert.rs lines 184-205.\n */\nasync function checkIpfs(port: number): Promise<void> {\n try {\n const url = `http://127.0.0.1:${port}/api/v0/version`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 2000);\n\n const response = await fetch(url, {\n method: \"POST\",\n signal: controller.signal,\n });\n\n clearTimeout(timeout);\n\n if (response.ok) {\n console.log(`✓ IPFS is available at 127.0.0.1:${port}`);\n } else {\n throw new Error(`✗ IPFS daemon returned error: ${response.status}`);\n }\n } catch (e) {\n if (e instanceof Error && e.name === \"AbortError\") {\n throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: connection timeout`);\n }\n throw new Error(\n `✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}`,\n );\n }\n}\n\n/**\n * Check if Hubert server is available.\n */\nasync function checkServer(host: string, port: number): Promise<void> {\n try {\n const url = `http://${host}:${port}/health`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 2000);\n\n const response = await fetch(url, {\n method: \"GET\",\n signal: controller.signal,\n });\n\n clearTimeout(timeout);\n\n if (response.ok) {\n const json = (await response.json()) as { server?: string; version?: string };\n if (json.server === \"hubert\") {\n const version = json.version ?? \"unknown\";\n console.log(`✓ Hubert server is available at ${host}:${port} (version ${version})`);\n } else {\n throw new Error(`✗ Server at ${host}:${port} is not a Hubert server`);\n }\n } else {\n throw new Error(`✗ Server at ${host}:${port} is not available (status: ${response.status})`);\n }\n } catch (e) {\n if (e instanceof Error && e.name === \"AbortError\") {\n throw new Error(`✗ Server is not available at ${host}:${port}: connection timeout`);\n }\n throw new Error(\n `✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}`,\n );\n }\n}\n\n// =============================================================================\n// Put Functions\n// =============================================================================\n\n/**\n * Put envelope to Mainline DHT.\n *\n * Port of `put_mainline()` from bin/hubert.rs lines 207-221.\n */\nasync function putMainline(arid: ARID, envelope: Envelope, verbose: boolean): Promise<void> {\n const store = await MainlineDhtKv.create();\n try {\n await store.put(arid, envelope, undefined, verbose);\n if (verbose) {\n verbosePrintln(\"✓ Stored envelope at ARID\");\n }\n } finally {\n await store.destroy();\n }\n}\n\n/**\n * Put envelope to IPFS.\n *\n * Port of `put_ipfs()` from bin/hubert.rs lines 223-250.\n */\nasync function putIpfs(\n arid: ARID,\n envelope: Envelope,\n port: number,\n pin: boolean,\n verbose: boolean,\n): Promise<void> {\n const url = `http://127.0.0.1:${port}`;\n const store = new IpfsKv(url).withPinContent(pin);\n const result = await store.put(arid, envelope, undefined, verbose);\n\n if (verbose) {\n verbosePrintln(\"✓ Stored envelope at ARID\");\n }\n\n // Extract and print CID if pinning was requested\n if (pin) {\n const cidPart = result.split(\"ipfs://\")[1];\n if (cidPart) {\n console.log(`CID: ${cidPart}`);\n }\n }\n}\n\n/**\n * Put envelope to Hybrid storage.\n *\n * Port of `put_hybrid()` from bin/hubert.rs lines 278-308.\n */\nasync function putHybrid(\n arid: ARID,\n envelope: Envelope,\n port: number,\n pin: boolean,\n verbose: boolean,\n): Promise<void> {\n const url = `http://127.0.0.1:${port}`;\n const store = (await HybridKv.create(url)).withPinContent(pin);\n try {\n const result = await store.put(arid, envelope, undefined, verbose);\n\n if (verbose) {\n verbosePrintln(\"✓ Stored envelope at ARID\");\n }\n\n // Extract and print CID if pinning was requested and IPFS was used\n if (pin && result.includes(\"ipfs://\")) {\n const cidPart = result.split(\"ipfs://\")[1];\n if (cidPart) {\n console.log(`CID: ${cidPart}`);\n }\n }\n } finally {\n await store.destroy();\n }\n}\n\n/**\n * Put envelope to Hubert server.\n *\n * Port of `put_server()` from bin/hubert.rs lines 324-344.\n */\nasync function putServer(\n host: string,\n port: number,\n arid: ARID,\n envelope: Envelope,\n ttl: number | undefined,\n verbose: boolean,\n): Promise<void> {\n const url = `http://${host}:${port}`;\n const store = new ServerKvClient(url);\n await store.put(arid, envelope, ttl, verbose);\n if (verbose) {\n verbosePrintln(\"✓ Stored envelope at ARID\");\n }\n}\n\n// =============================================================================\n// Get Functions\n// =============================================================================\n\n/**\n * Get envelope from Mainline DHT.\n *\n * Port of `get_mainline()` from bin/hubert.rs lines 252-262.\n */\nasync function getMainline(\n arid: ARID,\n timeout: number,\n verbose: boolean,\n): Promise<Envelope | null> {\n const store = await MainlineDhtKv.create();\n try {\n return await store.get(arid, timeout, verbose);\n } finally {\n await store.destroy();\n }\n}\n\n/**\n * Get envelope from IPFS.\n *\n * Port of `get_ipfs()` from bin/hubert.rs lines 264-276.\n */\nasync function getIpfs(\n arid: ARID,\n timeout: number,\n port: number,\n verbose: boolean,\n): Promise<Envelope | null> {\n const url = `http://127.0.0.1:${port}`;\n const store = new IpfsKv(url);\n return await store.get(arid, timeout, verbose);\n}\n\n/**\n * Get envelope from Hybrid storage.\n *\n * Port of `get_hybrid()` from bin/hubert.rs lines 310-322.\n */\nasync function getHybrid(\n arid: ARID,\n timeout: number,\n port: number,\n verbose: boolean,\n): Promise<Envelope | null> {\n const url = `http://127.0.0.1:${port}`;\n const store = await HybridKv.create(url);\n try {\n return await store.get(arid, timeout, verbose);\n } finally {\n await store.destroy();\n }\n}\n\n/**\n * Get envelope from Hubert server.\n *\n * Port of `get_server()` from bin/hubert.rs lines 346-361.\n */\nasync function getServer(\n host: string,\n port: number,\n arid: ARID,\n timeout: number,\n verbose: boolean,\n): Promise<Envelope | null> {\n const url = `http://${host}:${port}`;\n const store = new ServerKvClient(url);\n return await store.get(arid, timeout, verbose);\n}\n\n// =============================================================================\n// CLI Setup\n// =============================================================================\n\nconst program = new Command();\n\nprogram\n .name(\"hubert\")\n .description(\"Distributed substrate for multiparty transactions\")\n .version(\"1.0.0-alpha.1\")\n .option(\"-v, --verbose\", \"Enable verbose logging\", false);\n\n// Generate command\nconst generateCmd = program\n .command(\"generate\")\n .description(\"Generate a new ARID or example Envelope\");\n\ngenerateCmd\n .command(\"arid\")\n .description(\"Generate a new ARID\")\n .action(() => {\n const arid = ARID.new();\n console.log(arid.urString());\n });\n\ngenerateCmd\n .command(\"envelope <size>\")\n .description(\"Generate a test envelope with random data\")\n .action((sizeStr: string) => {\n const size = parseInt(sizeStr, 10);\n if (isNaN(size) || size < 0) {\n console.error(\"Size must be a positive integer\");\n process.exit(1);\n }\n const envelope = generateRandomEnvelope(size);\n console.log(envelope.urString());\n });\n\n// Put command\nprogram\n .command(\"put <arid> <envelope>\")\n .description(\"Store an envelope at an ARID\")\n .option(\"-s, --storage <backend>\", \"Storage backend to use\", \"mainline\")\n .option(\"--host <host>\", \"Server host (for --storage server)\")\n .option(\"--port <port>\", \"Port (for --storage server/ipfs/hybrid)\")\n .option(\"--ttl <seconds>\", \"Time-to-live in seconds (for --storage server)\")\n .option(\"--pin\", \"Pin content in IPFS (only for --storage ipfs or --storage hybrid)\", false)\n .action(\n async (\n aridStr: string,\n envelopeStr: string,\n options: {\n storage: StorageBackend;\n host?: string;\n port?: string;\n ttl?: string;\n pin: boolean;\n },\n ) => {\n const verbose = program.opts()[\"verbose\"] as boolean;\n const storage = options.storage;\n const port = options.port ? parseInt(options.port, 10) : undefined;\n const ttl = options.ttl ? parseInt(options.ttl, 10) : undefined;\n\n try {\n // Validate options based on storage backend\n if (storage === \"mainline\") {\n if (port !== undefined) {\n throw new Error(\"--port option is not supported for --storage mainline\");\n }\n if (options.host !== undefined) {\n throw new Error(\"--host option is not supported for --storage mainline\");\n }\n if (ttl !== undefined) {\n throw new Error(\"--ttl option is only supported for --storage server\");\n }\n if (options.pin) {\n throw new Error(\n \"--pin option is only supported for --storage ipfs or --storage hybrid\",\n );\n }\n } else if (storage === \"ipfs\") {\n if (options.host !== undefined) {\n throw new Error(\n \"--host option is not supported for --storage ipfs (always uses 127.0.0.1)\",\n );\n }\n if (ttl !== undefined) {\n throw new Error(\"--ttl option is only supported for --storage server\");\n }\n } else if (storage === \"hybrid\") {\n if (options.host !== undefined) {\n throw new Error(\n \"--host option is not supported for --storage hybrid (always uses 127.0.0.1)\",\n );\n }\n if (ttl !== undefined) {\n throw new Error(\"--ttl option is only supported for --storage server\");\n }\n } else if (storage === \"server\") {\n if (options.pin) {\n throw new Error(\n \"--pin option is only supported for --storage ipfs or --storage hybrid\",\n );\n }\n }\n\n const arid = parseArid(aridStr);\n const envelope = parseEnvelope(envelopeStr);\n\n switch (storage) {\n case \"mainline\":\n await putMainline(arid, envelope, verbose);\n console.log(\"Stored in Mainline DHT\");\n break;\n case \"ipfs\":\n await putIpfs(arid, envelope, port ?? 5001, options.pin, verbose);\n console.log(\"Stored in IPFS\");\n break;\n case \"hybrid\":\n await putHybrid(arid, envelope, port ?? 5001, options.pin, verbose);\n console.log(\"Stored in Hybrid storage\");\n break;\n case \"server\": {\n const host = options.host ?? \"127.0.0.1\";\n await putServer(host, port ?? 45678, arid, envelope, ttl, verbose);\n console.log(\"Stored in server\");\n break;\n }\n }\n } catch (e) {\n console.error(e instanceof Error ? e.message : e);\n process.exit(1);\n }\n },\n );\n\n// Get command\nprogram\n .command(\"get <arid>\")\n .description(\"Retrieve an envelope by ARID\")\n .option(\"-s, --storage <backend>\", \"Storage backend to use\", \"mainline\")\n .option(\"--host <host>\", \"Server host (for --storage server)\")\n .option(\"--port <port>\", \"Port (for --storage server/ipfs/hybrid)\")\n .option(\"-t, --timeout <seconds>\", \"Maximum time to wait in seconds\", \"30\")\n .action(\n async (\n aridStr: string,\n options: {\n storage: StorageBackend;\n host?: string;\n port?: string;\n timeout: string;\n },\n ) => {\n const verbose = program.opts()[\"verbose\"] as boolean;\n const storage = options.storage;\n const port = options.port ? parseInt(options.port, 10) : undefined;\n const timeout = parseInt(options.timeout, 10);\n\n try {\n // Validate options based on storage backend\n if (storage === \"mainline\") {\n if (port !== undefined) {\n throw new Error(\"--port option is not supported for --storage mainline\");\n }\n if (options.host !== undefined) {\n throw new Error(\"--host option is not supported for --storage mainline\");\n }\n } else if (storage === \"ipfs\") {\n if (options.host !== undefined) {\n throw new Error(\n \"--host option is not supported for --storage ipfs (always uses 127.0.0.1)\",\n );\n }\n } else if (storage === \"hybrid\") {\n if (options.host !== undefined) {\n throw new Error(\n \"--host option is not supported for --storage hybrid (always uses 127.0.0.1)\",\n );\n }\n }\n\n const arid = parseArid(aridStr);\n\n let envelope: Envelope | null;\n switch (storage) {\n case \"mainline\":\n envelope = await getMainline(arid, timeout, verbose);\n break;\n case \"ipfs\":\n envelope = await getIpfs(arid, timeout, port ?? 5001, verbose);\n break;\n case \"hybrid\":\n envelope = await getHybrid(arid, timeout, port ?? 5001, verbose);\n break;\n case \"server\": {\n const host = options.host ?? \"127.0.0.1\";\n envelope = await getServer(host, port ?? 45678, arid, timeout, verbose);\n break;\n }\n }\n\n if (envelope) {\n console.log(envelope.urString());\n } else {\n throw new Error(`Value not found within ${timeout} seconds`);\n }\n } catch (e) {\n console.error(e instanceof Error ? e.message : e);\n process.exit(1);\n }\n },\n );\n\n// Check command\nprogram\n .command(\"check\")\n .description(\"Check if storage backend is available\")\n .option(\"-s, --storage <backend>\", \"Storage backend to use\", \"mainline\")\n .option(\"--host <host>\", \"Server host (for --storage server)\")\n .option(\"--port <port>\", \"Port (for --storage server/ipfs/hybrid)\")\n .action(async (options: { storage: StorageBackend; host?: string; port?: string }) => {\n const storage = options.storage;\n const port = options.port ? parseInt(options.port, 10) : undefined;\n\n try {\n // Validate options based on storage backend\n if (storage === \"mainline\") {\n if (port !== undefined) {\n throw new Error(\"--port option is not supported for --storage mainline\");\n }\n if (options.host !== undefined) {\n throw new Error(\"--host option is not supported for --storage mainline\");\n }\n } else if (storage === \"ipfs\") {\n if (options.host !== undefined) {\n throw new Error(\n \"--host option is not supported for --storage ipfs (always uses 127.0.0.1)\",\n );\n }\n } else if (storage === \"hybrid\") {\n if (options.host !== undefined) {\n throw new Error(\n \"--host option is not supported for --storage hybrid (always uses 127.0.0.1)\",\n );\n }\n }\n\n switch (storage) {\n case \"mainline\":\n await checkMainline();\n break;\n case \"ipfs\":\n await checkIpfs(port ?? 5001);\n break;\n case \"hybrid\":\n await checkMainline();\n await checkIpfs(port ?? 5001);\n console.log(\"✓ Hybrid storage is available (DHT + IPFS)\");\n break;\n case \"server\": {\n const host = options.host ?? \"127.0.0.1\";\n await checkServer(host, port ?? 45678);\n break;\n }\n }\n } catch (e) {\n console.error(e instanceof Error ? e.message : e);\n process.exit(1);\n }\n });\n\n// Server command\nprogram\n .command(\"server\")\n .description(\"Start the Hubert HTTP server\")\n .option(\"--port <port>\", \"Port for the server to listen on\", \"45678\")\n .option(\"--sqlite <path>\", \"SQLite database file path for persistent storage\")\n .action(async (options: { port: string; sqlite?: string }) => {\n const verbose = program.opts()[\"verbose\"] as boolean;\n const port = parseInt(options.port, 10);\n\n try {\n const config: ServerConfig = {\n port,\n maxTtl: 86400, // 24 hours\n verbose,\n };\n\n if (options.sqlite) {\n // Use SQLite storage\n let sqlitePath = options.sqlite;\n // Check if it's a directory\n const fs = await import(\"fs\");\n try {\n const stats = fs.statSync(sqlitePath);\n if (stats.isDirectory()) {\n sqlitePath = path.join(sqlitePath, \"hubert.sqlite\");\n }\n } catch {\n // Path doesn't exist, treat as file path\n }\n\n const store = new SqliteKv(sqlitePath);\n const server = Server.newSqlite(config, store);\n console.log(`Starting Hubert server on port ${port} with SQLite storage: ${sqlitePath}`);\n await server.run();\n } else {\n // Use in-memory storage\n const server = Server.newMemory(config);\n console.log(`Starting Hubert server on port ${port} with in-memory storage`);\n await server.run();\n }\n } catch (e) {\n console.error(e instanceof Error ? e.message : e);\n process.exit(1);\n }\n });\n\n// Parse and run\nprogram.parse();\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|