@bcts/hubert 1.0.0-alpha.20 → 1.0.0-alpha.22
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 +2 -1
- package/dist/arid-derivation-CNfUKUp-.cjs.map +1 -1
- package/dist/arid-derivation-CbqACjdg.mjs.map +1 -1
- package/dist/bin/hubert.cjs +14 -10
- package/dist/bin/hubert.cjs.map +1 -1
- package/dist/bin/hubert.mjs +14 -10
- package/dist/bin/hubert.mjs.map +1 -1
- package/dist/hybrid/index.cjs +3 -3
- package/dist/hybrid/index.d.cts +2 -2
- package/dist/hybrid/index.d.mts +2 -2
- package/dist/hybrid/index.mjs +3 -3
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +9 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +9 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/ipfs/index.cjs +1 -1
- package/dist/ipfs/index.d.cts +2 -2
- package/dist/ipfs/index.d.mts +2 -2
- package/dist/ipfs/index.mjs +1 -1
- package/dist/{kv-DmjKQe11.cjs → kv-43DJmrPf.cjs} +14 -2
- package/dist/kv-43DJmrPf.cjs.map +1 -0
- package/dist/{kv-CmxPWVB1.mjs → kv-B40echkB.mjs} +16 -4
- package/dist/kv-B40echkB.mjs.map +1 -0
- package/dist/{kv-BhFoL8bc.mjs → kv-B7_Pf6f_.mjs} +14 -2
- package/dist/kv-B7_Pf6f_.mjs.map +1 -0
- package/dist/{kv-DJiKvypY.mjs → kv-BEtE9QLd.mjs} +6 -2
- package/dist/kv-BEtE9QLd.mjs.map +1 -0
- package/dist/{kv-Bv__Pl2s.d.cts → kv-CSpwZXM_.d.mts} +2 -2
- package/dist/kv-CSpwZXM_.d.mts.map +1 -0
- package/dist/{kv-1qBQRbV5.cjs → kv-CZtOUp0W.cjs} +6 -2
- package/dist/kv-CZtOUp0W.cjs.map +1 -0
- package/dist/{kv-BXu_sOvl.d.cts → kv-Cp3eaPPw.d.mts} +2 -2
- package/dist/kv-Cp3eaPPw.d.mts.map +1 -0
- package/dist/{kv-BmCAYeR7.cjs → kv-D-WtD2qw.cjs} +10 -2
- package/dist/kv-D-WtD2qw.cjs.map +1 -0
- package/dist/{kv-BcjifWIY.d.mts → kv-DCWXudlw.d.cts} +2 -2
- package/dist/kv-DCWXudlw.d.cts.map +1 -0
- package/dist/{kv-CVvMuP73.d.mts → kv-DHNW9N05.d.mts} +2 -2
- package/dist/kv-DHNW9N05.d.mts.map +1 -0
- package/dist/{kv-BS5Z28iJ.d.mts → kv-DwQqrf8p.d.cts} +2 -2
- package/dist/kv-DwQqrf8p.d.cts.map +1 -0
- package/dist/{kv-DPTr4DWU.d.cts → kv-Sbl4aWVr.d.mts} +2 -2
- package/dist/kv-Sbl4aWVr.d.mts.map +1 -0
- package/dist/{kv-BZB64lt0.d.cts → kv-TUuvNh-U.d.cts} +2 -2
- package/dist/kv-TUuvNh-U.d.cts.map +1 -0
- package/dist/{kv-DfzRmYtR.cjs → kv-XBcZgOlm.cjs} +16 -4
- package/dist/kv-XBcZgOlm.cjs.map +1 -0
- package/dist/{kv-DVYfnjvh.mjs → kv-lG8DtKJ5.mjs} +10 -2
- package/dist/kv-lG8DtKJ5.mjs.map +1 -0
- package/dist/{kv-akxfGRZi.d.mts → kv-lfyDP0PB.d.cts} +2 -2
- package/dist/kv-lfyDP0PB.d.cts.map +1 -0
- package/dist/{kv-store-nL8CboDh.d.mts → kv-store-CvTocPmI.d.mts} +5 -1
- package/dist/kv-store-CvTocPmI.d.mts.map +1 -0
- package/dist/{kv-store-ww-AUyLd.d.cts → kv-store-DjdrGR9V.d.cts} +5 -1
- package/dist/kv-store-DjdrGR9V.d.cts.map +1 -0
- package/dist/{logging-hmzNzifq.mjs → logging-BqzOubRL.mjs} +9 -1
- package/dist/logging-BqzOubRL.mjs.map +1 -0
- package/dist/{logging-qc9uMgil.cjs → logging-DW4R-zV6.cjs} +9 -1
- package/dist/logging-DW4R-zV6.cjs.map +1 -0
- package/dist/mainline/index.cjs +1 -1
- package/dist/mainline/index.d.cts +2 -2
- package/dist/mainline/index.d.mts +2 -2
- package/dist/mainline/index.mjs +1 -1
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.mts +2 -2
- package/dist/server/index.mjs +1 -1
- package/package.json +14 -25
- package/src/arid-derivation.ts +4 -0
- package/src/bin/hubert.ts +15 -3
- package/src/error.ts +4 -0
- package/src/hybrid/error.ts +4 -0
- package/src/hybrid/index.ts +4 -0
- package/src/hybrid/kv.ts +4 -0
- package/src/hybrid/reference.ts +4 -0
- package/src/index.ts +4 -0
- package/src/ipfs/error.ts +4 -0
- package/src/ipfs/index.ts +4 -0
- package/src/ipfs/kv.ts +4 -0
- package/src/ipfs/value.ts +4 -0
- package/src/kv-store.ts +4 -0
- package/src/logging.ts +4 -0
- package/src/mainline/error.ts +4 -0
- package/src/mainline/index.ts +4 -0
- package/src/mainline/kv.ts +4 -0
- package/src/server/error.ts +4 -0
- package/src/server/index.ts +4 -0
- package/src/server/kv.ts +4 -0
- package/src/server/memory-kv.ts +4 -0
- package/src/server/server-kv.ts +4 -0
- package/src/server/server.ts +4 -0
- package/src/server/sqlite-kv.ts +4 -0
- package/dist/kv-1qBQRbV5.cjs.map +0 -1
- package/dist/kv-BS5Z28iJ.d.mts.map +0 -1
- package/dist/kv-BXu_sOvl.d.cts.map +0 -1
- package/dist/kv-BZB64lt0.d.cts.map +0 -1
- package/dist/kv-BcjifWIY.d.mts.map +0 -1
- package/dist/kv-BhFoL8bc.mjs.map +0 -1
- package/dist/kv-BmCAYeR7.cjs.map +0 -1
- package/dist/kv-Bv__Pl2s.d.cts.map +0 -1
- package/dist/kv-CVvMuP73.d.mts.map +0 -1
- package/dist/kv-CmxPWVB1.mjs.map +0 -1
- package/dist/kv-DJiKvypY.mjs.map +0 -1
- package/dist/kv-DPTr4DWU.d.cts.map +0 -1
- package/dist/kv-DVYfnjvh.mjs.map +0 -1
- package/dist/kv-DfzRmYtR.cjs.map +0 -1
- package/dist/kv-DmjKQe11.cjs.map +0 -1
- package/dist/kv-akxfGRZi.d.mts.map +0 -1
- package/dist/kv-store-nL8CboDh.d.mts.map +0 -1
- package/dist/kv-store-ww-AUyLd.d.cts.map +0 -1
- package/dist/logging-hmzNzifq.mjs.map +0 -1
- package/dist/logging-qc9uMgil.cjs.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Copyright © 2025 Blockchain Commons, LLC
|
|
2
|
-
Copyright © 2025-2026
|
|
2
|
+
Copyright © 2025-2026 Parity Technologies
|
|
3
|
+
|
|
3
4
|
|
|
4
5
|
Redistribution and use in source and binary forms, with or without modification,
|
|
5
6
|
are permitted provided that the following conditions are met:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arid-derivation-CNfUKUp-.cjs","names":[],"sources":["../src/arid-derivation.ts"],"sourcesContent":["/**\n * ARID key derivation and obfuscation utilities.\n *\n * Port of arid_derivation.rs from hubert-rust.\n *\n * @module\n */\n\nimport { type ARID } from \"@bcts/components\";\nimport { hkdfHmacSha256 } from \"@bcts/crypto\";\nimport { chacha20 } from \"@noble/ciphers/chacha.js\";\n\n/**\n * Derive a deterministic key from an ARID using a specific salt.\n *\n * Uses HKDF to derive key material from the ARID, ensuring that:\n * - Same ARID always produces same key for a given salt\n * - Keys are cryptographically derived (not guessable)\n * - Collision resistance inherited from ARID\n * - No identifying information in the key (fully anonymized)\n *\n * Port of `derive_key()` from arid_derivation.rs lines 8-29.\n *\n * @param salt - Domain-specific salt to ensure different backends derive different keys\n * @param arid - The ARID to derive from\n * @param outputLen - Length of output in bytes (typically 20 or 32)\n * @returns Derived key bytes\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveKey(new TextEncoder().encode(\"my-salt\"), arid, 32);\n * ```\n */\nexport function deriveKey(salt: Uint8Array, arid: ARID, outputLen: number): Uint8Array {\n const aridBytes = arid.data();\n // Note: @bcts/crypto hkdfHmacSha256 takes (keyMaterial, salt, keyLen)\n // Rust bc-crypto takes (salt, ikm, keyLen)\n return hkdfHmacSha256(aridBytes, salt, outputLen);\n}\n\n/**\n * Salt for IPFS IPNS key derivation.\n * @internal\n */\nconst IPFS_KEY_NAME_SALT = new TextEncoder().encode(\"hubert-ipfs-ipns-v1\");\n\n/**\n * Salt for Mainline DHT key derivation.\n * @internal\n */\nconst MAINLINE_KEY_SALT = new TextEncoder().encode(\"hubert-mainline-dht-v1\");\n\n/**\n * Salt for obfuscation key derivation.\n * @internal\n */\nconst OBFUSCATION_SALT = new TextEncoder().encode(\"hubert-obfuscation-v1\");\n\n/**\n * Derive an IPNS key name from an ARID.\n *\n * Returns a 64-character hex string suitable for use as an IPFS key name.\n *\n * Port of `derive_ipfs_key_name()` from arid_derivation.rs lines 31-37.\n *\n * @param arid - The ARID to derive from\n * @returns 64-character hex string\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const keyName = deriveIpfsKeyName(arid);\n * // => \"a1b2c3d4e5f6...\" (64 hex characters)\n * ```\n */\nexport function deriveIpfsKeyName(arid: ARID): string {\n const keyBytes = deriveKey(IPFS_KEY_NAME_SALT, arid, 32);\n return bytesToHex(keyBytes);\n}\n\n/**\n * Derive Mainline DHT key material from an ARID.\n *\n * Returns 20 bytes of key material (SHA-1 compatible length).\n *\n * Port of `derive_mainline_key()` from arid_derivation.rs lines 39-45.\n *\n * @param arid - The ARID to derive from\n * @returns 20 bytes of key material\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveMainlineKey(arid);\n * // => Uint8Array(20) [...]\n * ```\n */\nexport function deriveMainlineKey(arid: ARID): Uint8Array {\n return deriveKey(MAINLINE_KEY_SALT, arid, 20);\n}\n\n/**\n * Obfuscate or deobfuscate data using ChaCha20 with an ARID-derived key.\n *\n * This function uses ChaCha20 as a stream cipher to XOR the data with a\n * keystream derived from the ARID. Since XOR is symmetric, the same function\n * is used for both obfuscation and deobfuscation.\n *\n * The result appears as uniform random data to anyone who doesn't have the\n * ARID, hiding both the structure and content of the reference envelope.\n *\n * Port of `obfuscate_with_arid()` from arid_derivation.rs lines 47-91.\n *\n * @param arid - The ARID used to derive the obfuscation key\n * @param data - The data to obfuscate or deobfuscate\n * @returns The obfuscated (or deobfuscated) data\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const obfuscated = obfuscateWithArid(arid, plaintext);\n * const deobfuscated = obfuscateWithArid(arid, obfuscated);\n * // deobfuscated === plaintext\n * ```\n */\nexport function obfuscateWithArid(arid: ARID, data: Uint8Array): Uint8Array {\n if (data.length === 0) {\n return new Uint8Array(0);\n }\n\n // Derive a 32-byte key from the ARID using HKDF with domain-specific salt\n const key = deriveKey(OBFUSCATION_SALT, arid, 32);\n\n // Derive IV from the key (last 12 bytes, reversed)\n // Match Rust: key.iter().rev().take(12).copied().collect()\n const iv = new Uint8Array(12);\n for (let i = 0; i < 12; i++) {\n iv[i] = key[31 - i];\n }\n\n // Use ChaCha20 to XOR the data\n // @noble/ciphers chacha20 takes (key, nonce, data) and returns encrypted data\n return chacha20(key, iv, data);\n}\n\n/**\n * Convert bytes to lowercase hex string.\n * @internal\n */\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"arid-derivation-CNfUKUp-.cjs","names":[],"sources":["../src/arid-derivation.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * ARID key derivation and obfuscation utilities.\n *\n * Port of arid_derivation.rs from hubert-rust.\n *\n * @module\n */\n\nimport { type ARID } from \"@bcts/components\";\nimport { hkdfHmacSha256 } from \"@bcts/crypto\";\nimport { chacha20 } from \"@noble/ciphers/chacha.js\";\n\n/**\n * Derive a deterministic key from an ARID using a specific salt.\n *\n * Uses HKDF to derive key material from the ARID, ensuring that:\n * - Same ARID always produces same key for a given salt\n * - Keys are cryptographically derived (not guessable)\n * - Collision resistance inherited from ARID\n * - No identifying information in the key (fully anonymized)\n *\n * Port of `derive_key()` from arid_derivation.rs lines 8-29.\n *\n * @param salt - Domain-specific salt to ensure different backends derive different keys\n * @param arid - The ARID to derive from\n * @param outputLen - Length of output in bytes (typically 20 or 32)\n * @returns Derived key bytes\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveKey(new TextEncoder().encode(\"my-salt\"), arid, 32);\n * ```\n */\nexport function deriveKey(salt: Uint8Array, arid: ARID, outputLen: number): Uint8Array {\n const aridBytes = arid.data();\n // Note: @bcts/crypto hkdfHmacSha256 takes (keyMaterial, salt, keyLen)\n // Rust bc-crypto takes (salt, ikm, keyLen)\n return hkdfHmacSha256(aridBytes, salt, outputLen);\n}\n\n/**\n * Salt for IPFS IPNS key derivation.\n * @internal\n */\nconst IPFS_KEY_NAME_SALT = new TextEncoder().encode(\"hubert-ipfs-ipns-v1\");\n\n/**\n * Salt for Mainline DHT key derivation.\n * @internal\n */\nconst MAINLINE_KEY_SALT = new TextEncoder().encode(\"hubert-mainline-dht-v1\");\n\n/**\n * Salt for obfuscation key derivation.\n * @internal\n */\nconst OBFUSCATION_SALT = new TextEncoder().encode(\"hubert-obfuscation-v1\");\n\n/**\n * Derive an IPNS key name from an ARID.\n *\n * Returns a 64-character hex string suitable for use as an IPFS key name.\n *\n * Port of `derive_ipfs_key_name()` from arid_derivation.rs lines 31-37.\n *\n * @param arid - The ARID to derive from\n * @returns 64-character hex string\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const keyName = deriveIpfsKeyName(arid);\n * // => \"a1b2c3d4e5f6...\" (64 hex characters)\n * ```\n */\nexport function deriveIpfsKeyName(arid: ARID): string {\n const keyBytes = deriveKey(IPFS_KEY_NAME_SALT, arid, 32);\n return bytesToHex(keyBytes);\n}\n\n/**\n * Derive Mainline DHT key material from an ARID.\n *\n * Returns 20 bytes of key material (SHA-1 compatible length).\n *\n * Port of `derive_mainline_key()` from arid_derivation.rs lines 39-45.\n *\n * @param arid - The ARID to derive from\n * @returns 20 bytes of key material\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveMainlineKey(arid);\n * // => Uint8Array(20) [...]\n * ```\n */\nexport function deriveMainlineKey(arid: ARID): Uint8Array {\n return deriveKey(MAINLINE_KEY_SALT, arid, 20);\n}\n\n/**\n * Obfuscate or deobfuscate data using ChaCha20 with an ARID-derived key.\n *\n * This function uses ChaCha20 as a stream cipher to XOR the data with a\n * keystream derived from the ARID. Since XOR is symmetric, the same function\n * is used for both obfuscation and deobfuscation.\n *\n * The result appears as uniform random data to anyone who doesn't have the\n * ARID, hiding both the structure and content of the reference envelope.\n *\n * Port of `obfuscate_with_arid()` from arid_derivation.rs lines 47-91.\n *\n * @param arid - The ARID used to derive the obfuscation key\n * @param data - The data to obfuscate or deobfuscate\n * @returns The obfuscated (or deobfuscated) data\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const obfuscated = obfuscateWithArid(arid, plaintext);\n * const deobfuscated = obfuscateWithArid(arid, obfuscated);\n * // deobfuscated === plaintext\n * ```\n */\nexport function obfuscateWithArid(arid: ARID, data: Uint8Array): Uint8Array {\n if (data.length === 0) {\n return new Uint8Array(0);\n }\n\n // Derive a 32-byte key from the ARID using HKDF with domain-specific salt\n const key = deriveKey(OBFUSCATION_SALT, arid, 32);\n\n // Derive IV from the key (last 12 bytes, reversed)\n // Match Rust: key.iter().rev().take(12).copied().collect()\n const iv = new Uint8Array(12);\n for (let i = 0; i < 12; i++) {\n iv[i] = key[31 - i];\n }\n\n // Use ChaCha20 to XOR the data\n // @noble/ciphers chacha20 takes (key, nonce, data) and returns encrypted data\n return chacha20(key, iv, data);\n}\n\n/**\n * Convert bytes to lowercase hex string.\n * @internal\n */\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,UAAU,MAAkB,MAAY,WAA+B;AAIrF,yCAHkB,KAAK,MAAM,EAGI,MAAM,UAAU;;;;;;AAOnD,MAAM,qBAAqB,IAAI,aAAa,CAAC,OAAO,sBAAsB;;;;;AAM1E,MAAM,oBAAoB,IAAI,aAAa,CAAC,OAAO,yBAAyB;;;;;AAM5E,MAAM,mBAAmB,IAAI,aAAa,CAAC,OAAO,wBAAwB;;;;;;;;;;;;;;;;;;AAmB1E,SAAgB,kBAAkB,MAAoB;AAEpD,QAAO,WADU,UAAU,oBAAoB,MAAM,GAAG,CAC7B;;;;;;;;;;;;;;;;;;;AAoB7B,SAAgB,kBAAkB,MAAwB;AACxD,QAAO,UAAU,mBAAmB,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;AA2B/C,SAAgB,kBAAkB,MAAY,MAA8B;AAC1E,KAAI,KAAK,WAAW,EAClB,QAAO,IAAI,WAAW,EAAE;CAI1B,MAAM,MAAM,UAAU,kBAAkB,MAAM,GAAG;CAIjD,MAAM,KAAK,IAAI,WAAW,GAAG;AAC7B,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,IACtB,IAAG,KAAK,IAAI,KAAK;AAKnB,+CAAgB,KAAK,IAAI,KAAK;;;;;;AAOhC,SAAS,WAAW,OAA2B;AAC7C,QAAO,MAAM,KAAK,MAAM,CACrB,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC3C,KAAK,GAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arid-derivation-CbqACjdg.mjs","names":[],"sources":["../src/arid-derivation.ts"],"sourcesContent":["/**\n * ARID key derivation and obfuscation utilities.\n *\n * Port of arid_derivation.rs from hubert-rust.\n *\n * @module\n */\n\nimport { type ARID } from \"@bcts/components\";\nimport { hkdfHmacSha256 } from \"@bcts/crypto\";\nimport { chacha20 } from \"@noble/ciphers/chacha.js\";\n\n/**\n * Derive a deterministic key from an ARID using a specific salt.\n *\n * Uses HKDF to derive key material from the ARID, ensuring that:\n * - Same ARID always produces same key for a given salt\n * - Keys are cryptographically derived (not guessable)\n * - Collision resistance inherited from ARID\n * - No identifying information in the key (fully anonymized)\n *\n * Port of `derive_key()` from arid_derivation.rs lines 8-29.\n *\n * @param salt - Domain-specific salt to ensure different backends derive different keys\n * @param arid - The ARID to derive from\n * @param outputLen - Length of output in bytes (typically 20 or 32)\n * @returns Derived key bytes\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveKey(new TextEncoder().encode(\"my-salt\"), arid, 32);\n * ```\n */\nexport function deriveKey(salt: Uint8Array, arid: ARID, outputLen: number): Uint8Array {\n const aridBytes = arid.data();\n // Note: @bcts/crypto hkdfHmacSha256 takes (keyMaterial, salt, keyLen)\n // Rust bc-crypto takes (salt, ikm, keyLen)\n return hkdfHmacSha256(aridBytes, salt, outputLen);\n}\n\n/**\n * Salt for IPFS IPNS key derivation.\n * @internal\n */\nconst IPFS_KEY_NAME_SALT = new TextEncoder().encode(\"hubert-ipfs-ipns-v1\");\n\n/**\n * Salt for Mainline DHT key derivation.\n * @internal\n */\nconst MAINLINE_KEY_SALT = new TextEncoder().encode(\"hubert-mainline-dht-v1\");\n\n/**\n * Salt for obfuscation key derivation.\n * @internal\n */\nconst OBFUSCATION_SALT = new TextEncoder().encode(\"hubert-obfuscation-v1\");\n\n/**\n * Derive an IPNS key name from an ARID.\n *\n * Returns a 64-character hex string suitable for use as an IPFS key name.\n *\n * Port of `derive_ipfs_key_name()` from arid_derivation.rs lines 31-37.\n *\n * @param arid - The ARID to derive from\n * @returns 64-character hex string\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const keyName = deriveIpfsKeyName(arid);\n * // => \"a1b2c3d4e5f6...\" (64 hex characters)\n * ```\n */\nexport function deriveIpfsKeyName(arid: ARID): string {\n const keyBytes = deriveKey(IPFS_KEY_NAME_SALT, arid, 32);\n return bytesToHex(keyBytes);\n}\n\n/**\n * Derive Mainline DHT key material from an ARID.\n *\n * Returns 20 bytes of key material (SHA-1 compatible length).\n *\n * Port of `derive_mainline_key()` from arid_derivation.rs lines 39-45.\n *\n * @param arid - The ARID to derive from\n * @returns 20 bytes of key material\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveMainlineKey(arid);\n * // => Uint8Array(20) [...]\n * ```\n */\nexport function deriveMainlineKey(arid: ARID): Uint8Array {\n return deriveKey(MAINLINE_KEY_SALT, arid, 20);\n}\n\n/**\n * Obfuscate or deobfuscate data using ChaCha20 with an ARID-derived key.\n *\n * This function uses ChaCha20 as a stream cipher to XOR the data with a\n * keystream derived from the ARID. Since XOR is symmetric, the same function\n * is used for both obfuscation and deobfuscation.\n *\n * The result appears as uniform random data to anyone who doesn't have the\n * ARID, hiding both the structure and content of the reference envelope.\n *\n * Port of `obfuscate_with_arid()` from arid_derivation.rs lines 47-91.\n *\n * @param arid - The ARID used to derive the obfuscation key\n * @param data - The data to obfuscate or deobfuscate\n * @returns The obfuscated (or deobfuscated) data\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const obfuscated = obfuscateWithArid(arid, plaintext);\n * const deobfuscated = obfuscateWithArid(arid, obfuscated);\n * // deobfuscated === plaintext\n * ```\n */\nexport function obfuscateWithArid(arid: ARID, data: Uint8Array): Uint8Array {\n if (data.length === 0) {\n return new Uint8Array(0);\n }\n\n // Derive a 32-byte key from the ARID using HKDF with domain-specific salt\n const key = deriveKey(OBFUSCATION_SALT, arid, 32);\n\n // Derive IV from the key (last 12 bytes, reversed)\n // Match Rust: key.iter().rev().take(12).copied().collect()\n const iv = new Uint8Array(12);\n for (let i = 0; i < 12; i++) {\n iv[i] = key[31 - i];\n }\n\n // Use ChaCha20 to XOR the data\n // @noble/ciphers chacha20 takes (key, nonce, data) and returns encrypted data\n return chacha20(key, iv, data);\n}\n\n/**\n * Convert bytes to lowercase hex string.\n * @internal\n */\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"arid-derivation-CbqACjdg.mjs","names":[],"sources":["../src/arid-derivation.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * ARID key derivation and obfuscation utilities.\n *\n * Port of arid_derivation.rs from hubert-rust.\n *\n * @module\n */\n\nimport { type ARID } from \"@bcts/components\";\nimport { hkdfHmacSha256 } from \"@bcts/crypto\";\nimport { chacha20 } from \"@noble/ciphers/chacha.js\";\n\n/**\n * Derive a deterministic key from an ARID using a specific salt.\n *\n * Uses HKDF to derive key material from the ARID, ensuring that:\n * - Same ARID always produces same key for a given salt\n * - Keys are cryptographically derived (not guessable)\n * - Collision resistance inherited from ARID\n * - No identifying information in the key (fully anonymized)\n *\n * Port of `derive_key()` from arid_derivation.rs lines 8-29.\n *\n * @param salt - Domain-specific salt to ensure different backends derive different keys\n * @param arid - The ARID to derive from\n * @param outputLen - Length of output in bytes (typically 20 or 32)\n * @returns Derived key bytes\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveKey(new TextEncoder().encode(\"my-salt\"), arid, 32);\n * ```\n */\nexport function deriveKey(salt: Uint8Array, arid: ARID, outputLen: number): Uint8Array {\n const aridBytes = arid.data();\n // Note: @bcts/crypto hkdfHmacSha256 takes (keyMaterial, salt, keyLen)\n // Rust bc-crypto takes (salt, ikm, keyLen)\n return hkdfHmacSha256(aridBytes, salt, outputLen);\n}\n\n/**\n * Salt for IPFS IPNS key derivation.\n * @internal\n */\nconst IPFS_KEY_NAME_SALT = new TextEncoder().encode(\"hubert-ipfs-ipns-v1\");\n\n/**\n * Salt for Mainline DHT key derivation.\n * @internal\n */\nconst MAINLINE_KEY_SALT = new TextEncoder().encode(\"hubert-mainline-dht-v1\");\n\n/**\n * Salt for obfuscation key derivation.\n * @internal\n */\nconst OBFUSCATION_SALT = new TextEncoder().encode(\"hubert-obfuscation-v1\");\n\n/**\n * Derive an IPNS key name from an ARID.\n *\n * Returns a 64-character hex string suitable for use as an IPFS key name.\n *\n * Port of `derive_ipfs_key_name()` from arid_derivation.rs lines 31-37.\n *\n * @param arid - The ARID to derive from\n * @returns 64-character hex string\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const keyName = deriveIpfsKeyName(arid);\n * // => \"a1b2c3d4e5f6...\" (64 hex characters)\n * ```\n */\nexport function deriveIpfsKeyName(arid: ARID): string {\n const keyBytes = deriveKey(IPFS_KEY_NAME_SALT, arid, 32);\n return bytesToHex(keyBytes);\n}\n\n/**\n * Derive Mainline DHT key material from an ARID.\n *\n * Returns 20 bytes of key material (SHA-1 compatible length).\n *\n * Port of `derive_mainline_key()` from arid_derivation.rs lines 39-45.\n *\n * @param arid - The ARID to derive from\n * @returns 20 bytes of key material\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const key = deriveMainlineKey(arid);\n * // => Uint8Array(20) [...]\n * ```\n */\nexport function deriveMainlineKey(arid: ARID): Uint8Array {\n return deriveKey(MAINLINE_KEY_SALT, arid, 20);\n}\n\n/**\n * Obfuscate or deobfuscate data using ChaCha20 with an ARID-derived key.\n *\n * This function uses ChaCha20 as a stream cipher to XOR the data with a\n * keystream derived from the ARID. Since XOR is symmetric, the same function\n * is used for both obfuscation and deobfuscation.\n *\n * The result appears as uniform random data to anyone who doesn't have the\n * ARID, hiding both the structure and content of the reference envelope.\n *\n * Port of `obfuscate_with_arid()` from arid_derivation.rs lines 47-91.\n *\n * @param arid - The ARID used to derive the obfuscation key\n * @param data - The data to obfuscate or deobfuscate\n * @returns The obfuscated (or deobfuscated) data\n * @category ARID Derivation\n *\n * @example\n * ```typescript\n * const obfuscated = obfuscateWithArid(arid, plaintext);\n * const deobfuscated = obfuscateWithArid(arid, obfuscated);\n * // deobfuscated === plaintext\n * ```\n */\nexport function obfuscateWithArid(arid: ARID, data: Uint8Array): Uint8Array {\n if (data.length === 0) {\n return new Uint8Array(0);\n }\n\n // Derive a 32-byte key from the ARID using HKDF with domain-specific salt\n const key = deriveKey(OBFUSCATION_SALT, arid, 32);\n\n // Derive IV from the key (last 12 bytes, reversed)\n // Match Rust: key.iter().rev().take(12).copied().collect()\n const iv = new Uint8Array(12);\n for (let i = 0; i < 12; i++) {\n iv[i] = key[31 - i];\n }\n\n // Use ChaCha20 to XOR the data\n // @noble/ciphers chacha20 takes (key, nonce, data) and returns encrypted data\n return chacha20(key, iv, data);\n}\n\n/**\n * Convert bytes to lowercase hex string.\n * @internal\n */\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,UAAU,MAAkB,MAAY,WAA+B;AAIrF,QAAO,eAHW,KAAK,MAAM,EAGI,MAAM,UAAU;;;;;;AAOnD,MAAM,qBAAqB,IAAI,aAAa,CAAC,OAAO,sBAAsB;;;;;AAM1E,MAAM,oBAAoB,IAAI,aAAa,CAAC,OAAO,yBAAyB;;;;;AAM5E,MAAM,mBAAmB,IAAI,aAAa,CAAC,OAAO,wBAAwB;;;;;;;;;;;;;;;;;;AAmB1E,SAAgB,kBAAkB,MAAoB;AAEpD,QAAO,WADU,UAAU,oBAAoB,MAAM,GAAG,CAC7B;;;;;;;;;;;;;;;;;;;AAoB7B,SAAgB,kBAAkB,MAAwB;AACxD,QAAO,UAAU,mBAAmB,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;AA2B/C,SAAgB,kBAAkB,MAAY,MAA8B;AAC1E,KAAI,KAAK,WAAW,EAClB,QAAO,IAAI,WAAW,EAAE;CAI1B,MAAM,MAAM,UAAU,kBAAkB,MAAM,GAAG;CAIjD,MAAM,KAAK,IAAI,WAAW,GAAG;AAC7B,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,IACtB,IAAG,KAAK,IAAI,KAAK;AAKnB,QAAO,SAAS,KAAK,IAAI,KAAK;;;;;;AAOhC,SAAS,WAAW,OAA2B;AAC7C,QAAO,MAAM,KAAK,MAAM,CACrB,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC3C,KAAK,GAAG"}
|
package/dist/bin/hubert.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const require_chunk = require('../chunk-C0xms8kb.cjs');
|
|
3
|
-
const require_logging = require('../logging-
|
|
3
|
+
const require_logging = require('../logging-DW4R-zV6.cjs');
|
|
4
4
|
require('../arid-derivation-CNfUKUp-.cjs');
|
|
5
|
-
const require_kv = require('../kv-
|
|
6
|
-
const require_kv$1 = require('../kv-
|
|
7
|
-
const require_kv$2 = require('../kv-
|
|
8
|
-
const require_kv$3 = require('../kv-
|
|
5
|
+
const require_kv = require('../kv-43DJmrPf.cjs');
|
|
6
|
+
const require_kv$1 = require('../kv-CZtOUp0W.cjs');
|
|
7
|
+
const require_kv$2 = require('../kv-D-WtD2qw.cjs');
|
|
8
|
+
const require_kv$3 = require('../kv-XBcZgOlm.cjs');
|
|
9
9
|
require('../index.cjs');
|
|
10
10
|
let path = require("path");
|
|
11
11
|
path = require_chunk.__toESM(path);
|
|
@@ -16,6 +16,10 @@ let _bcts_rand = require("@bcts/rand");
|
|
|
16
16
|
|
|
17
17
|
//#region src/bin/hubert.ts
|
|
18
18
|
/**
|
|
19
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
20
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
21
|
+
*
|
|
22
|
+
*
|
|
19
23
|
* Hubert: Secure Distributed Substrate for Multiparty Transactions
|
|
20
24
|
*
|
|
21
25
|
* A command-line tool for storing and retrieving Gordian Envelopes using
|
|
@@ -68,7 +72,7 @@ async function checkMainline() {
|
|
|
68
72
|
await (await require_kv$2.MainlineDhtKv.create()).destroy();
|
|
69
73
|
console.log("✓ Mainline DHT is available");
|
|
70
74
|
} catch (e) {
|
|
71
|
-
throw new Error(`✗ Mainline DHT is not available: ${e instanceof Error ? e.message : e}
|
|
75
|
+
throw new Error(`✗ Mainline DHT is not available: ${e instanceof Error ? e.message : e}`, { cause: e });
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
/**
|
|
@@ -89,8 +93,8 @@ async function checkIpfs(port) {
|
|
|
89
93
|
if (response.ok) console.log(`✓ IPFS is available at 127.0.0.1:${port}`);
|
|
90
94
|
else throw new Error(`✗ IPFS daemon returned error: ${response.status}`);
|
|
91
95
|
} catch (e) {
|
|
92
|
-
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: connection timeout
|
|
93
|
-
throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}
|
|
96
|
+
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: connection timeout`, { cause: e });
|
|
97
|
+
throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}`, { cause: e });
|
|
94
98
|
}
|
|
95
99
|
}
|
|
96
100
|
/**
|
|
@@ -114,8 +118,8 @@ async function checkServer(host, port) {
|
|
|
114
118
|
} else throw new Error(`✗ Server at ${host}:${port} is not a Hubert server`);
|
|
115
119
|
} else throw new Error(`✗ Server at ${host}:${port} is not available (status: ${response.status})`);
|
|
116
120
|
} catch (e) {
|
|
117
|
-
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ Server is not available at ${host}:${port}: connection timeout
|
|
118
|
-
throw new Error(`✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}
|
|
121
|
+
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ Server is not available at ${host}:${port}: connection timeout`, { cause: e });
|
|
122
|
+
throw new Error(`✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}`, { cause: e });
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
/**
|
package/dist/bin/hubert.cjs.map
CHANGED
|
@@ -1 +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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"}
|
|
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 * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\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 cause: e,\n });\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 cause: e,\n });\n }\n throw new Error(\n `✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}`,\n { cause: 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 cause: e,\n });\n }\n throw new Error(\n `✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}`,\n { cause: 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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"}
|
package/dist/bin/hubert.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as verbosePrintln } from "../logging-
|
|
2
|
+
import { i as verbosePrintln } from "../logging-BqzOubRL.mjs";
|
|
3
3
|
import "../arid-derivation-CbqACjdg.mjs";
|
|
4
|
-
import { n as Server, o as SqliteKv, t as ServerKvClient } from "../kv-
|
|
5
|
-
import { t as IpfsKv } from "../kv-
|
|
6
|
-
import { t as MainlineDhtKv } from "../kv-
|
|
7
|
-
import { t as HybridKv } from "../kv-
|
|
4
|
+
import { n as Server, o as SqliteKv, t as ServerKvClient } from "../kv-B7_Pf6f_.mjs";
|
|
5
|
+
import { t as IpfsKv } from "../kv-BEtE9QLd.mjs";
|
|
6
|
+
import { t as MainlineDhtKv } from "../kv-lG8DtKJ5.mjs";
|
|
7
|
+
import { t as HybridKv } from "../kv-B40echkB.mjs";
|
|
8
8
|
import "../index.mjs";
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { ARID } from "@bcts/components";
|
|
@@ -14,6 +14,10 @@ import { randomData } from "@bcts/rand";
|
|
|
14
14
|
|
|
15
15
|
//#region src/bin/hubert.ts
|
|
16
16
|
/**
|
|
17
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
18
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
19
|
+
*
|
|
20
|
+
*
|
|
17
21
|
* Hubert: Secure Distributed Substrate for Multiparty Transactions
|
|
18
22
|
*
|
|
19
23
|
* A command-line tool for storing and retrieving Gordian Envelopes using
|
|
@@ -66,7 +70,7 @@ async function checkMainline() {
|
|
|
66
70
|
await (await MainlineDhtKv.create()).destroy();
|
|
67
71
|
console.log("✓ Mainline DHT is available");
|
|
68
72
|
} catch (e) {
|
|
69
|
-
throw new Error(`✗ Mainline DHT is not available: ${e instanceof Error ? e.message : e}
|
|
73
|
+
throw new Error(`✗ Mainline DHT is not available: ${e instanceof Error ? e.message : e}`, { cause: e });
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
76
|
/**
|
|
@@ -87,8 +91,8 @@ async function checkIpfs(port) {
|
|
|
87
91
|
if (response.ok) console.log(`✓ IPFS is available at 127.0.0.1:${port}`);
|
|
88
92
|
else throw new Error(`✗ IPFS daemon returned error: ${response.status}`);
|
|
89
93
|
} catch (e) {
|
|
90
|
-
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: connection timeout
|
|
91
|
-
throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}
|
|
94
|
+
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: connection timeout`, { cause: e });
|
|
95
|
+
throw new Error(`✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}`, { cause: e });
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
/**
|
|
@@ -112,8 +116,8 @@ async function checkServer(host, port) {
|
|
|
112
116
|
} else throw new Error(`✗ Server at ${host}:${port} is not a Hubert server`);
|
|
113
117
|
} else throw new Error(`✗ Server at ${host}:${port} is not available (status: ${response.status})`);
|
|
114
118
|
} catch (e) {
|
|
115
|
-
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ Server is not available at ${host}:${port}: connection timeout
|
|
116
|
-
throw new Error(`✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}
|
|
119
|
+
if (e instanceof Error && e.name === "AbortError") throw new Error(`✗ Server is not available at ${host}:${port}: connection timeout`, { cause: e });
|
|
120
|
+
throw new Error(`✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}`, { cause: e });
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
/**
|
package/dist/bin/hubert.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hubert.mjs","names":[],"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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"}
|
|
1
|
+
{"version":3,"file":"hubert.mjs","names":[],"sources":["../../src/bin/hubert.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\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 cause: e,\n });\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 cause: e,\n });\n }\n throw new Error(\n `✗ IPFS is not available at 127.0.0.1:${port}: ${e instanceof Error ? e.message : e}`,\n { cause: 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 cause: e,\n });\n }\n throw new Error(\n `✗ Server is not available at ${host}:${port}: ${e instanceof Error ? e.message : e}`,\n { cause: 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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"}
|
package/dist/hybrid/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
require('../arid-derivation-CNfUKUp-.cjs');
|
|
3
|
-
require('../kv-
|
|
4
|
-
require('../kv-
|
|
5
|
-
const require_kv$2 = require('../kv-
|
|
3
|
+
require('../kv-CZtOUp0W.cjs');
|
|
4
|
+
require('../kv-D-WtD2qw.cjs');
|
|
5
|
+
const require_kv$2 = require('../kv-XBcZgOlm.cjs');
|
|
6
6
|
|
|
7
7
|
exports.ContentNotFoundError = require_kv$2.ContentNotFoundError;
|
|
8
8
|
exports.HybridError = require_kv$2.HybridError;
|
package/dist/hybrid/index.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "../kv-store-
|
|
2
|
-
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "../kv-
|
|
1
|
+
import "../kv-store-DjdrGR9V.cjs";
|
|
2
|
+
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "../kv-DwQqrf8p.cjs";
|
|
3
3
|
export { ContentNotFoundError, HybridError, HybridKv, InvalidReferenceAridError, NoIdAssertionError, NotReferenceEnvelopeError, createReferenceEnvelope, extractReferenceArid, isReferenceEnvelope };
|
package/dist/hybrid/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "../kv-store-
|
|
2
|
-
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "../kv-
|
|
1
|
+
import "../kv-store-CvTocPmI.mjs";
|
|
2
|
+
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "../kv-CSpwZXM_.mjs";
|
|
3
3
|
export { ContentNotFoundError, HybridError, HybridKv, InvalidReferenceAridError, NoIdAssertionError, NotReferenceEnvelopeError, createReferenceEnvelope, extractReferenceArid, isReferenceEnvelope };
|
package/dist/hybrid/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../arid-derivation-CbqACjdg.mjs";
|
|
2
|
-
import "../kv-
|
|
3
|
-
import "../kv-
|
|
4
|
-
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "../kv-
|
|
2
|
+
import "../kv-BEtE9QLd.mjs";
|
|
3
|
+
import "../kv-lG8DtKJ5.mjs";
|
|
4
|
+
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "../kv-B40echkB.mjs";
|
|
5
5
|
|
|
6
6
|
export { ContentNotFoundError, HybridError, HybridKv, InvalidReferenceAridError, NoIdAssertionError, NotReferenceEnvelopeError, createReferenceEnvelope, extractReferenceArid, isReferenceEnvelope };
|
package/dist/index.cjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_logging = require('./logging-
|
|
2
|
+
const require_logging = require('./logging-DW4R-zV6.cjs');
|
|
3
3
|
const require_arid_derivation = require('./arid-derivation-CNfUKUp-.cjs');
|
|
4
|
-
const require_kv = require('./kv-
|
|
4
|
+
const require_kv = require('./kv-43DJmrPf.cjs');
|
|
5
5
|
require('./server/index.cjs');
|
|
6
|
-
const require_kv$1 = require('./kv-
|
|
6
|
+
const require_kv$1 = require('./kv-CZtOUp0W.cjs');
|
|
7
7
|
require('./ipfs/index.cjs');
|
|
8
|
-
const require_kv$2 = require('./kv-
|
|
8
|
+
const require_kv$2 = require('./kv-D-WtD2qw.cjs');
|
|
9
9
|
require('./mainline/index.cjs');
|
|
10
|
-
const require_kv$3 = require('./kv-
|
|
10
|
+
const require_kv$3 = require('./kv-XBcZgOlm.cjs');
|
|
11
11
|
require('./hybrid/index.cjs');
|
|
12
12
|
|
|
13
13
|
exports.AlreadyExistsError = require_logging.AlreadyExistsError;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { a as IoError, i as InvalidAridError, n as AlreadyExistsError, o as NotFoundError, r as HubertError, t as KvStore } from "./kv-store-
|
|
2
|
-
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "./kv-
|
|
1
|
+
import { a as IoError, i as InvalidAridError, n as AlreadyExistsError, o as NotFoundError, r as HubertError, t as KvStore } from "./kv-store-DjdrGR9V.cjs";
|
|
2
|
+
import { a as ContentNotFoundError, c as NoIdAssertionError, i as isReferenceEnvelope, l as NotReferenceEnvelopeError, n as createReferenceEnvelope, o as HybridError, r as extractReferenceArid, s as InvalidReferenceAridError, t as HybridKv } from "./kv-DwQqrf8p.cjs";
|
|
3
3
|
import "./hybrid/index.cjs";
|
|
4
|
-
import { a as ServerKv, c as SqliteKv, d as ServerGeneralError, f as ServerNetworkError, i as defaultServerConfig, l as MemoryKv, m as SqliteError, n as Server, o as createMemoryKv, p as ServerParseError, r as ServerConfig, s as createSqliteKv, t as ServerKvClient, u as ServerError } from "./kv-
|
|
4
|
+
import { a as ServerKv, c as SqliteKv, d as ServerGeneralError, f as ServerNetworkError, i as defaultServerConfig, l as MemoryKv, m as SqliteError, n as Server, o as createMemoryKv, p as ServerParseError, r as ServerConfig, s as createSqliteKv, t as ServerKvClient, u as ServerError } from "./kv-TUuvNh-U.cjs";
|
|
5
5
|
import "./server/index.cjs";
|
|
6
|
-
import { a as EnvelopeTooLargeError, c as IpfsTimeoutError, i as pinCid, l as UnexpectedIpnsPathFormatError, n as addBytes, o as IpfsDaemonError, r as catBytes, s as IpfsError, t as IpfsKv } from "./kv-
|
|
6
|
+
import { a as EnvelopeTooLargeError, c as IpfsTimeoutError, i as pinCid, l as UnexpectedIpnsPathFormatError, n as addBytes, o as IpfsDaemonError, r as catBytes, s as IpfsError, t as IpfsKv } from "./kv-lfyDP0PB.cjs";
|
|
7
7
|
import "./ipfs/index.cjs";
|
|
8
|
-
import { a as MainlineIoError, c as ValueTooLargeError, i as MainlineError, n as DecodeIdError, o as PutMutableError, r as DhtError, s as PutQueryError, t as MainlineDhtKv } from "./kv-
|
|
8
|
+
import { a as MainlineIoError, c as ValueTooLargeError, i as MainlineError, n as DecodeIdError, o as PutMutableError, r as DhtError, s as PutQueryError, t as MainlineDhtKv } from "./kv-DCWXudlw.cjs";
|
|
9
9
|
import "./mainline/index.cjs";
|
|
10
10
|
import { ARID } from "@bcts/components";
|
|
11
11
|
|
|
@@ -97,6 +97,10 @@ declare function obfuscateWithArid(arid: ARID, data: Uint8Array): Uint8Array;
|
|
|
97
97
|
//#endregion
|
|
98
98
|
//#region src/logging.d.ts
|
|
99
99
|
/**
|
|
100
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
101
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
102
|
+
*
|
|
103
|
+
*
|
|
100
104
|
* Logging utilities for verbose output with timestamps.
|
|
101
105
|
*
|
|
102
106
|
* Port of logging.rs from hubert-rust.
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/arid-derivation.ts","../src/logging.ts"],"mappings":";;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/arid-derivation.ts","../src/logging.ts"],"mappings":";;;;;;;;;;;;AAsCA;;;;;;;;;;;;;;;;AA0CA;;;;;AAsBA;AAhEA,iBAAgB,SAAA,CAAU,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,IAAA,EAAM,SAAA,WAAoB,UAAA;;;;;;;;AA4F5E;;;;;;;;;;iBAlDgB,iBAAA,CAAkB,IAAA,EAAM,IAAA;;;;;;;;ACvDxC;;;;;AA4BA;;;;;iBDiDgB,iBAAA,CAAkB,IAAA,EAAM,IAAA,GAAO,UAAA;;;;;ACb/C;;;;;;;;;;;;;;;;;;;;iBDyCgB,iBAAA,CAAkB,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,UAAA,GAAa,UAAA;;;;;;;;;;;;;;;AA5FjE;;;;;;;;;;;;iBCbgB,SAAA,CAAA;;;;ADuDhB;;;;;AAsBA;;;;;;iBCjDgB,cAAA,CAAe,OAAA;;;AD6E/B;;;;;;;;;;iBC3DgB,eAAA,CAAA;;;;;;;;AA9ChB;;;;;AA4BA;;iBAoCgB,cAAA,CAAA"}
|