@mblaney/holster 2.1.4 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/holster.js +3 -3
- package/build/holster.js.map +4 -4
- package/dist/holster.js +3 -3
- package/dist/holster.js.map +4 -4
- package/package.json +2 -2
- package/src/holster.js +30 -0
- package/src/nested.js +89 -0
- package/src/wire.js +22 -12
- package/ts/src/holster.ts +40 -7
- package/ts/src/nested.ts +101 -0
- package/ts/src/schemas.ts +1 -0
- package/ts/src/wire.ts +21 -11
package/build/holster.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/utils.js", "../src/dup.js", "../src/get.js", "../src/array.js", "../src/buffer.js", "../src/sea-utils.js", "../src/sea.js", "../src/ham.js", "../src/radix.js", "../src/radisk.js", "../src/store.js", "../src/wire.js", "../src/user.js", "../src/holster.js"],
|
|
4
|
-
"sourcesContent": ["export const num = {\n is: n => {\n if (n instanceof Array) return false\n\n if (typeof n === \"number\") return !isNaN(n)\n\n if (typeof n === \"string\") {\n const parsed = parseFloat(n)\n return !isNaN(parsed) && isFinite(parsed)\n }\n\n return false\n },\n}\n\nexport const obj = {\n is: o => {\n if (!o || typeof o !== \"object\") return false\n\n const toString = Object.prototype.toString.call(o)\n const match = toString.match(/^\\[object (\\w+)\\]$/)\n return o.constructor === Object || (match && match[1] === \"Object\")\n },\n map: (list, cb, o) => {\n var keys = Object.keys(list)\n for (let i = 0; i < keys.length; i++) {\n let result = cb(list[keys[i]], keys[i], o)\n if (typeof result !== \"undefined\") return result\n }\n },\n put: (o, key, value) => {\n if (!o) o = {}\n o[key] = value\n return o\n },\n del: (o, key) => {\n if (!o) return\n\n o[key] = null\n delete o[key]\n return o\n },\n}\n\nconst map_soul = (soul, key, o) => {\n // If id is already defined AND we're still looping through the object,\n // then it is considered invalid.\n if (o.id) {\n o.id = false\n return\n }\n\n if (key === \"#\" && typeof soul === \"string\") {\n o.id = soul\n return\n }\n\n // If there exists anything else on the object that isn't the soul,\n // then it is considered invalid.\n o.id = false\n}\n\n// Check if an object is a soul relation, ie {'#': 'UUID'}\nexport const rel = {\n is: value => {\n if (value && value[\"#\"] && !value._ && obj.is(value)) {\n let o = {}\n obj.map(value, map_soul, o)\n if (o.id) return o.id\n }\n\n return false\n },\n // Convert a soul into a relation and return it.\n ify: soul => obj.put({}, \"#\", soul),\n}\n\nexport const userSignature = \"_holster_user_signature\"\nexport const userPublicKey = \"_holster_user_public_key\"\n\n// graph converts objects to graph format with updated states,\n// with optional meta data to verify signed data.\nexport const graph = (soul, data, sig, pub, timestamp) => {\n const g = {[soul]: {_: {\"#\": soul, \">\": {}}}}\n\n for (const [key, value] of Object.entries(data)) {\n if (key !== \"_\" && key !== userPublicKey && key !== userSignature) {\n g[soul][key] = value\n g[soul]._[\">\"][key] = timestamp || Date.now()\n }\n }\n if (sig && pub && timestamp) {\n g[soul]._[\"s\"] = {[timestamp]: sig}\n g[soul][userPublicKey] = pub\n g[soul]._[\">\"][userPublicKey] = timestamp\n }\n return g\n}\n\nexport const match = (lex, key) => {\n // Null is used to match listeners on souls, which don't provide a key.\n if (typeof key === \"undefined\") return lex === null\n\n if (typeof lex === \"undefined\") return true\n\n if (typeof lex === \"string\") return lex === key\n\n // Array support: check if key is in the array\n if (Array.isArray(lex)) return lex.includes(key)\n\n if (!obj.is(lex) || !key) return false\n\n const prefix = lex[\"*\"]\n if (prefix) return key.slice(0, prefix.length) === prefix\n\n const gt = lex[\">\"]\n const lt = lex[\"<\"]\n if (gt && lt) return key >= gt && key <= lt\n\n if (gt) return key >= gt\n\n if (lt) return key <= lt\n\n return false\n}\n\nexport const text = {\n random: length => {\n var s = \"\"\n const c = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n if (!length) length = 24\n for (let i = 0; i < length; i++) {\n s += c.charAt(Math.floor(Math.random() * c.length))\n }\n return s\n },\n}\n", "const Dup = () => {\n const maxAge = 9000\n const dup = {store: {}}\n dup.check = id => (dup.store[id] ? dup.track(id) : false)\n dup.track = id => {\n // Keep the liveliness of the message up while it is being received.\n dup.store[id] = Date.now()\n if (!dup.expiry) {\n dup.expiry = setTimeout(() => {\n const now = Date.now()\n Object.keys(dup.store).forEach(id => {\n if (now - dup.store[id] > maxAge) delete dup.store[id]\n })\n dup.expiry = null\n }, maxAge)\n // Don't block process exit \u2014 cleanup is best-effort.\n if (dup.expiry.unref) dup.expiry.unref()\n }\n return id\n }\n return dup\n}\n\nexport default Dup\n", "import {match, userPublicKey} from \"./utils.js\"\n\nconst Get = (lex, graph, fast) => {\n if (!lex || typeof lex !== \"object\") {\n throw new TypeError(\"lex must be an object\")\n }\n if (!graph || typeof graph !== \"object\") {\n throw new TypeError(\"graph must be an object\")\n }\n\n const soul = lex[\"#\"]\n if (!soul || typeof soul !== \"string\") {\n throw new TypeError(\"soul must be a string\")\n }\n\n if (!graph[soul]) return\n\n const node = {_: {\"#\": soul, \">\": {}}}\n let signatures = {}\n\n if (typeof lex[\".\"] === \"string\") {\n const key = lex[\".\"]\n if (typeof graph[soul][key] === \"undefined\") return\n\n node[key] = graph[soul][key]\n node._[\">\"][key] = graph[soul]._[\">\"][key]\n const state = graph[soul]._[\">\"][key]\n if (graph[soul]._[\"s\"] && graph[soul]._[\"s\"][state]) {\n signatures[state] = graph[soul]._[\"s\"][state]\n }\n\n // Always include userPublicKey for verification, regardless of filter\n if (userPublicKey && typeof graph[soul][userPublicKey] !== \"undefined\") {\n node[userPublicKey] = graph[soul][userPublicKey]\n node._[\">\"][userPublicKey] = graph[soul]._[\">\"][userPublicKey]\n const pkState = graph[soul]._[\">\"][userPublicKey]\n if (graph[soul]._[\"s\"] && graph[soul]._[\"s\"][pkState]) {\n signatures[pkState] = graph[soul]._[\"s\"][pkState]\n }\n }\n } else {\n // For fast requests, return properties currently in the graph. Otherwise\n // return undefined to ensure we get all matching properties from store.\n if (!fast) return\n\n let found = false\n for (const key of Object.keys(graph[soul])) {\n // Always include userPublicKey for verification, regardless of filter\n if (key !== \"_\" && (key === userPublicKey || match(lex[\".\"], key))) {\n node[key] = graph[soul][key]\n node._[\">\"][key] = graph[soul]._[\">\"][key]\n const state = graph[soul]._[\">\"][key]\n if (graph[soul]._[\"s\"] && graph[soul]._[\"s\"][state]) {\n signatures[state] = graph[soul]._[\"s\"][state]\n }\n found = true\n }\n }\n if (!found) return\n }\n if (Object.keys(signatures).length > 0) {\n node._[\"s\"] = signatures\n }\n return {[soul]: node}\n}\n\nexport default Get\n", "if (typeof btoa === \"undefined\") {\n globalThis.btoa = data => Buffer.from(data, \"binary\").toString(\"base64\")\n globalThis.atob = data => Buffer.from(data, \"base64\").toString(\"binary\")\n}\n\n// This is Array extended to have .toString([\"utf8\"|\"hex\"|\"base64\"])\nfunction SeaArray() {}\nObject.assign(SeaArray, {from: Array.from})\nSeaArray.prototype = Object.create(Array.prototype)\n\nSeaArray.prototype.toString = function (enc, start, end) {\n if (!enc) enc = \"utf8\"\n if (!start) start = 0\n\n end = end ? Math.min(Math.max(end, start), this.length) : this.length\n\n if (enc === \"hex\") {\n const buf = new Uint8Array(this.slice(start, end))\n return Array.from(buf, byte => byte.toString(16).padStart(2, \"0\")).join(\"\")\n }\n\n if (enc === \"utf8\") {\n return Array.from({length: end - start}, (_, i) => {\n const charCode = this[i + start]\n // Use unicode replacement character for invalid character codes.\n if (charCode < 0 || charCode > 0x10ffff) {\n return String.fromCharCode(0xfffd)\n }\n return String.fromCharCode(charCode)\n }).join(\"\")\n }\n\n if (enc === \"base64\") {\n const utf8String = Array.from({length: end - start}, (_, i) => {\n const charCode = this[i + start]\n if (charCode < 0 || charCode > 255) {\n return String.fromCharCode(0xfffd)\n }\n return String.fromCharCode(charCode)\n }).join(\"\")\n return btoa(utf8String)\n }\n}\n\nexport default SeaArray\n", "import SeaArray from \"./array.js\"\n\n// Security constants\nconst SECURITY_LIMITS = {\n MAX_BUFFER_SIZE: 10 * 1024 * 1024, // 10MB limit\n MAX_STRING_LENGTH: 1024 * 1024, // 1MB string limit\n}\n\n// Secure Buffer implementation for SEA.js\n// Compatible with NodeJS safe-buffer but with enhanced security\nfunction SafeBuffer(...props) {\n console.warn(\"new SafeBuffer() is deprecated, please use SafeBuffer.from()\")\n return SafeBuffer.from(...props)\n}\n\nSafeBuffer.prototype = Object.create(Array.prototype)\n\n// Input validation helpers\nconst validateStringInput = (input, encoding) => {\n if (typeof input !== \"string\") {\n throw new TypeError(\"Input must be a string for encoding: \" + encoding)\n }\n\n if (input.length > SECURITY_LIMITS.MAX_STRING_LENGTH) {\n throw new RangeError(\n `String too large: ${input.length} > ${SECURITY_LIMITS.MAX_STRING_LENGTH}`,\n )\n }\n}\n\nconst validateBufferSize = (size, operation = \"buffer operation\") => {\n if (size > SECURITY_LIMITS.MAX_BUFFER_SIZE) {\n throw new RangeError(\n `Buffer size too large for ${operation}: ${size} > ${SECURITY_LIMITS.MAX_BUFFER_SIZE}`,\n )\n }\n}\n\n// Secure hex parsing\nconst parseHexString = hexString => {\n validateStringInput(hexString, \"hex\")\n\n // Remove any whitespace and convert to lowercase\n const cleanHex = hexString.replace(/\\s/g, \"\").toLowerCase()\n\n // Validate hex format: only 0-9, a-f characters\n if (!/^[0-9a-f]*$/.test(cleanHex)) {\n throw new TypeError(\"Invalid hex string: contains non-hex characters\")\n }\n\n // Must be even length\n if (cleanHex.length % 2 !== 0) {\n throw new TypeError(\"Invalid hex string: must have even length\")\n }\n\n if (cleanHex.length === 0) {\n return new Uint8Array(0)\n }\n\n validateBufferSize(cleanHex.length / 2, \"hex parsing\")\n\n const bytes = new Uint8Array(cleanHex.length / 2)\n for (let i = 0; i < cleanHex.length; i += 2) {\n const hexByte = cleanHex.substr(i, 2)\n bytes[i / 2] = parseInt(hexByte, 16)\n }\n return bytes\n}\n\nconst encodeUtf8String = str => {\n validateStringInput(str, \"utf8\")\n\n try {\n // Use standard TextEncoder for proper UTF-8 encoding\n const encoder = new TextEncoder()\n const bytes = encoder.encode(str)\n\n validateBufferSize(bytes.length, \"UTF-8 encoding\")\n return bytes\n } catch (err) {\n throw new TypeError(\"Failed to encode UTF-8 string: \" + err.message)\n }\n}\n\nconst encodeBinaryString = str => {\n validateStringInput(str, \"binary\")\n\n validateBufferSize(str.length, \"binary encoding\")\n\n const bytes = new Uint8Array(str.length)\n for (let i = 0; i < str.length; i++) {\n const charCode = str.charCodeAt(i)\n\n // Binary strings should only contain bytes (0-255)\n if (charCode > 255) {\n throw new TypeError(\n `Invalid binary string: character at position ${i} exceeds byte range (${charCode} > 255)`,\n )\n }\n\n bytes[i] = charCode\n }\n return bytes\n}\n\n// Secure base64 decoding\nconst parseBase64String = base64String => {\n validateStringInput(base64String, \"base64\")\n\n // Remove any whitespace\n const cleanBase64 = base64String.replace(/\\s/g, \"\")\n\n // Validate base64 format\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleanBase64)) {\n throw new TypeError(\"Invalid base64 string: contains invalid characters\")\n }\n\n try {\n const decodedString = atob(cleanBase64)\n validateBufferSize(decodedString.length, \"base64 decoding\")\n\n const bytes = new Uint8Array(decodedString.length)\n for (let i = 0; i < decodedString.length; i++) {\n bytes[i] = decodedString.charCodeAt(i)\n }\n\n return bytes\n } catch (err) {\n throw new TypeError(\"Failed to decode base64 string: \" + err.message)\n }\n}\n\n// Secure array-like input processing\nconst processArrayLikeInput = input => {\n let bytes\n\n if (input instanceof ArrayBuffer) {\n validateBufferSize(input.byteLength, \"ArrayBuffer processing\")\n bytes = new Uint8Array(input)\n } else if (ArrayBuffer.isView(input)) {\n validateBufferSize(\n input.byteLength || input.length,\n \"TypedArray processing\",\n )\n bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength)\n } else if (Array.isArray(input)) {\n validateBufferSize(input.length, \"Array processing\")\n\n // Validate all array elements are valid byte values\n for (let i = 0; i < input.length; i++) {\n const val = input[i]\n if (\n typeof val !== \"number\" ||\n val < 0 ||\n val > 255 ||\n !Number.isInteger(val)\n ) {\n throw new TypeError(\n `Invalid byte value at index ${i}: ${val} (must be integer 0-255)`,\n )\n }\n }\n\n bytes = new Uint8Array(input)\n } else if (\n typeof input === \"object\" &&\n input !== null &&\n typeof input.byteLength === \"number\"\n ) {\n // Handle ArrayBuffer from different contexts (e.g. jsdom)\n validateBufferSize(input.byteLength, \"ArrayBuffer-like processing\")\n bytes = new Uint8Array(input)\n } else if (\n typeof input === \"object\" &&\n input !== null &&\n typeof input.length === \"number\"\n ) {\n // Handle array-like objects\n validateBufferSize(input.length, \"array-like processing\")\n\n const arr = Array.from(input)\n for (let i = 0; i < arr.length; i++) {\n const val = arr[i]\n if (\n typeof val !== \"number\" ||\n val < 0 ||\n val > 255 ||\n !Number.isInteger(val)\n ) {\n throw new TypeError(\n `Invalid byte value at index ${i}: ${val} (must be integer 0-255)`,\n )\n }\n }\n bytes = new Uint8Array(arr)\n } else {\n throw new TypeError(\"Unsupported input type: \" + typeof input)\n }\n\n return bytes\n}\n\nObject.assign(SafeBuffer, {\n from() {\n const argCount = arguments.length\n\n if (argCount === 0) {\n throw new TypeError(\"SafeBuffer.from() requires at least one argument\")\n }\n\n const input = arguments[0]\n\n if (input === null || input === undefined) {\n throw new TypeError(\"First argument must not be null or undefined\")\n }\n\n let bytes\n\n if (typeof input === \"string\") {\n const encoding = (arguments[1] || \"utf8\").toLowerCase()\n\n switch (encoding) {\n case \"hex\":\n bytes = parseHexString(input)\n break\n\n case \"utf8\":\n case \"utf-8\":\n bytes = encodeUtf8String(input)\n break\n\n case \"binary\":\n case \"latin1\":\n bytes = encodeBinaryString(input)\n break\n\n case \"base64\":\n bytes = parseBase64String(input)\n break\n\n case \"ascii\":\n // ASCII is subset of UTF-8, but validate range\n validateStringInput(input, \"ascii\")\n for (let i = 0; i < input.length; i++) {\n if (input.charCodeAt(i) > 127) {\n throw new TypeError(\n `Invalid ASCII character at position ${i}: ${input.charCodeAt(i)} > 127`,\n )\n }\n }\n bytes = encodeUtf8String(input) // Safe since ASCII is UTF-8 subset\n break\n\n default:\n throw new TypeError(\"Unknown encoding: \" + encoding)\n }\n } else {\n bytes = processArrayLikeInput(input)\n }\n\n if (!bytes || bytes.length === 0) {\n return SeaArray.from(new Uint8Array(0))\n }\n\n try {\n return SeaArray.from(bytes)\n } catch (err) {\n throw new Error(\"Failed to create SafeBuffer: \" + err.message)\n }\n },\n\n alloc(length, fill = 0) {\n if (typeof length !== \"number\" || !Number.isInteger(length) || length < 0) {\n throw new TypeError(\"Length must be a non-negative integer\")\n }\n\n validateBufferSize(length, \"buffer allocation\")\n\n // Validate fill value\n if (typeof fill === \"number\") {\n if (fill < 0 || fill > 255 || !Number.isInteger(fill)) {\n throw new TypeError(\"Fill value must be an integer between 0 and 255\")\n }\n } else if (typeof fill === \"string\") {\n if (fill.length !== 1) {\n throw new TypeError(\"Fill string must be exactly one character\")\n }\n fill = fill.charCodeAt(0)\n if (fill > 255) {\n throw new TypeError(\"Fill character code must be <= 255\")\n }\n } else {\n throw new TypeError(\"Fill must be a number or single character string\")\n }\n\n try {\n const buffer = new Uint8Array(length)\n if (fill !== 0) {\n buffer.fill(fill)\n }\n return SeaArray.from(buffer)\n } catch (err) {\n throw new Error(\"Failed to allocate buffer: \" + err.message)\n }\n },\n\n concat(arr) {\n if (!Array.isArray(arr)) {\n throw new TypeError(\"First argument must be an array\")\n }\n\n if (arr.length === 0) {\n return SeaArray.from(new Uint8Array(0))\n }\n\n // Validate all array elements and calculate total size\n let totalLength = 0\n const validatedBuffers = []\n\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i]\n\n if (!item) {\n throw new TypeError(`Array element at index ${i} is null or undefined`)\n }\n\n let bytes\n try {\n bytes = processArrayLikeInput(item)\n } catch (err) {\n throw new TypeError(\n `Invalid array element at index ${i}: ${err.message}`,\n )\n }\n\n totalLength += bytes.length\n validateBufferSize(totalLength, \"buffer concatenation\")\n\n validatedBuffers.push(bytes)\n }\n\n try {\n const result = new Uint8Array(totalLength)\n let offset = 0\n\n for (const buffer of validatedBuffers) {\n result.set(buffer, offset)\n offset += buffer.length\n }\n\n return SeaArray.from(result)\n } catch (err) {\n throw new Error(\"Failed to concatenate buffers: \" + err.message)\n }\n },\n\n // Helper method to check if object is SafeBuffer\n isBuffer(obj) {\n return (\n obj instanceof SeaArray ||\n (obj && typeof obj === \"object\" && obj.constructor === SafeBuffer)\n )\n },\n\n // Get byte length of string in specific encoding\n byteLength(string, encoding = \"utf8\") {\n if (typeof string !== \"string\") {\n throw new TypeError(\"First argument must be a string\")\n }\n\n switch (encoding.toLowerCase()) {\n case \"utf8\":\n case \"utf-8\":\n return new TextEncoder().encode(string).length\n\n case \"ascii\":\n case \"binary\":\n case \"latin1\":\n return string.length\n\n case \"base64\":\n const clean = string.replace(/\\s/g, \"\")\n return (\n Math.floor((clean.length * 3) / 4) - (clean.match(/=/g) || []).length\n )\n\n case \"hex\":\n return Math.floor(string.replace(/\\s/g, \"\").length / 2)\n\n default:\n throw new TypeError(\"Unknown encoding: \" + encoding)\n }\n },\n})\n\nSafeBuffer.prototype.from = SafeBuffer.from\nSafeBuffer.prototype.toString = function (\n encoding = \"utf8\",\n start = 0,\n end = this.length,\n) {\n // Input validation\n if (typeof encoding !== \"string\") {\n throw new TypeError(\"Encoding must be a string\")\n }\n\n if (typeof start !== \"number\" || !Number.isInteger(start) || start < 0) {\n throw new TypeError(\"Start must be a non-negative integer\")\n }\n\n if (typeof end !== \"number\" || !Number.isInteger(end) || end < start) {\n throw new TypeError(\"End must be an integer >= start\")\n }\n\n // Delegate to SeaArray with validation\n try {\n return SeaArray.prototype.toString.call(this, encoding, start, end)\n } catch (err) {\n throw new Error(\"Failed to convert buffer to string: \" + err.message)\n }\n}\n\nexport default SafeBuffer\n", "import SafeBuffer from \"./buffer.js\"\n\nconst isNode = typeof process !== \"undefined\" && process.versions?.node != null\nconst crypto = isNode\n ? (await import(/*webpackIgnore: true*/ \"node:crypto\")).webcrypto\n : globalThis.crypto\nexport const subtle = crypto.subtle\n\nexport const stringify = data => {\n return typeof data === \"string\" ? data : JSON.stringify(data)\n}\n\nexport const parse = text => {\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nexport const random = length => {\n const array = new Uint8Array(SafeBuffer.alloc(length))\n return SafeBuffer.from(crypto.getRandomValues(array))\n}\n\nexport const jwk = (pub, priv) => {\n const [x, y] = pub.split(\".\")\n const ops = priv ? [\"sign\"] : [\"verify\"]\n return {\n kty: \"EC\",\n crv: \"P-256\",\n x: x,\n y: y,\n d: priv,\n ext: true,\n key_ops: ops,\n }\n}\n\nexport const sha256 = async data => {\n const hash = await subtle.digest(\n {name: \"SHA-256\"},\n new TextEncoder().encode(stringify(data)),\n )\n return SafeBuffer.from(hash)\n}\n\nexport const aeskey = async (key, salt) => {\n const combined = key + salt.toString(\"utf8\")\n const hash = SafeBuffer.from(await sha256(combined), \"binary\")\n const jwk = keyToJwk(hash)\n return await subtle.importKey(\"jwk\", jwk, {name: \"AES-GCM\"}, false, [\n \"encrypt\",\n \"decrypt\",\n ])\n}\n\nconst keyToJwk = key => {\n const k = key\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/\\=/g, \"\")\n return {kty: \"oct\", k: k, ext: false, alg: \"A256GCM\"}\n}\n", "import {userPublicKey, userSignature} from \"./utils.js\"\nimport * as utils from \"./sea-utils.js\"\nimport SafeBuffer from \"./buffer.js\"\n\n// Security, Encryption, and Authorization: SEA.js from GunDB.\nconst SEA = {\n pair: async cb => {\n // ECDSA keys for signing/verifying.\n const ecdsa = await utils.subtle\n .generateKey({name: \"ECDSA\", namedCurve: \"P-256\"}, true, [\n \"sign\",\n \"verify\",\n ])\n .then(async keys => {\n const pub = await utils.subtle.exportKey(\"jwk\", keys.publicKey)\n return {\n priv: (await utils.subtle.exportKey(\"jwk\", keys.privateKey)).d,\n pub: pub.x + \".\" + pub.y,\n }\n })\n\n // ECDH keys for encryption/decryption.\n const ecdh = await utils.subtle\n .generateKey({name: \"ECDH\", namedCurve: \"P-256\"}, true, [\"deriveKey\"])\n .then(async keys => {\n const pub = await utils.subtle.exportKey(\"jwk\", keys.publicKey)\n return {\n epriv: (await utils.subtle.exportKey(\"jwk\", keys.privateKey)).d,\n epub: pub.x + \".\" + pub.y,\n }\n })\n\n const pair = {\n pub: ecdsa.pub,\n priv: ecdsa.priv,\n epub: ecdh.epub,\n epriv: ecdh.epriv,\n }\n if (cb) cb(pair)\n return pair\n },\n encrypt: async (data, pair, cb) => {\n if (!pair || !pair.epriv) {\n if (cb) cb(null)\n return null\n }\n\n const rand = {s: utils.random(9), iv: utils.random(15)}\n const ct = await utils.aeskey(pair.epriv, rand.s).then(aes => {\n return utils.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv: new Uint8Array(rand.iv),\n },\n aes,\n new TextEncoder().encode(utils.stringify(data)),\n )\n })\n const enc = {\n ct: SafeBuffer.from(ct, \"binary\").toString(\"base64\"),\n iv: rand.iv.toString(\"base64\"),\n s: rand.s.toString(\"base64\"),\n }\n if (cb) cb(enc)\n return enc\n },\n decrypt: async (enc, pair, cb) => {\n if (!enc || !enc.ct || !enc.iv || !enc.s || !pair || !pair.epriv) {\n if (cb) cb(null)\n return null\n }\n\n const data = {\n ct: SafeBuffer.from(enc.ct, \"base64\"),\n iv: SafeBuffer.from(enc.iv, \"base64\"),\n s: SafeBuffer.from(enc.s, \"base64\"),\n }\n try {\n const ct = await utils.aeskey(pair.epriv, data.s).then(aes => {\n return utils.subtle.decrypt(\n {\n name: \"AES-GCM\",\n iv: new Uint8Array(data.iv),\n tagLength: 128,\n },\n aes,\n new Uint8Array(data.ct),\n )\n })\n const dec = utils.parse(new TextDecoder(\"utf8\").decode(ct))\n if (cb) cb(dec)\n return dec\n } catch (err) {\n // An error will be thrown if the wrong key is used.\n if (cb) cb(null)\n return null\n }\n },\n verify: async (data, pair, cb) => {\n if (!pair || !pair.pub) {\n if (cb) cb(null)\n return null\n }\n\n const signed = utils.parse(data)\n const key = await utils.subtle.importKey(\n \"jwk\",\n utils.jwk(pair.pub),\n {name: \"ECDSA\", namedCurve: \"P-256\"},\n false,\n [\"verify\"],\n )\n\n let msg = {}\n if (typeof signed.m === \"string\") {\n msg = signed.m\n } else {\n // Allow data to be passed in with graph meta data,\n // (which should not be part of signature, so not verified).\n for (const k of Object.keys(signed.m).sort()) {\n if (k !== \"_\" && k !== userPublicKey && k !== userSignature) {\n msg[k] = signed.m[k]\n }\n }\n }\n const hash = await utils.sha256(msg)\n const sig = new Uint8Array(SafeBuffer.from(signed.s, \"base64\"))\n const alg = {name: \"ECDSA\", hash: {name: \"SHA-256\"}}\n if (await utils.subtle.verify(alg, key, sig, new Uint8Array(hash))) {\n const verified = utils.parse(signed.m)\n if (cb) cb(verified)\n return verified\n }\n\n if (cb) cb(null)\n return null\n },\n sign: async (data, pair, cb) => {\n if (!pair || !pair.pub || !pair.priv) {\n if (cb) cb(null)\n return null\n }\n\n let msg = {}\n if (typeof data === \"string\") {\n msg = data\n } else {\n const check = utils.parse(data)\n for (const k of Object.keys(check).sort()) {\n if (k !== \"_\" && k !== userPublicKey && k !== userSignature) {\n msg[k] = check[k]\n }\n }\n }\n const hash = await utils.sha256(msg)\n const jwk = utils.jwk(pair.pub, pair.priv)\n const alg = {name: \"ECDSA\", namedCurve: \"P-256\"}\n const sig = await utils.subtle\n .importKey(\"jwk\", jwk, alg, false, [\"sign\"])\n .then(key =>\n utils.subtle.sign(\n {name: \"ECDSA\", hash: {name: \"SHA-256\"}},\n key,\n new Uint8Array(hash),\n ),\n )\n const signed = {\n m: msg,\n s: SafeBuffer.from(sig, \"binary\").toString(\"base64\"),\n }\n\n if (cb) cb(signed)\n return signed\n },\n // Sign a timestamp to prove ownership of an update\n signTimestamp: async (timestamp, pair, cb) => {\n if (!pair || !pair.pub || !pair.priv) {\n if (cb) cb(null)\n return null\n }\n\n // Convert timestamp to string for consistent hashing\n const timestampStr = timestamp.toString()\n const hash = await utils.sha256(timestampStr)\n const jwk = utils.jwk(pair.pub, pair.priv)\n const alg = {name: \"ECDSA\", namedCurve: \"P-256\"}\n\n const sig = await utils.subtle\n .importKey(\"jwk\", jwk, alg, false, [\"sign\"])\n .then(key =>\n utils.subtle.sign(\n {name: \"ECDSA\", hash: {name: \"SHA-256\"}},\n key,\n new Uint8Array(hash),\n ),\n )\n\n const signature = SafeBuffer.from(sig, \"binary\").toString(\"base64\")\n\n if (cb) cb(signature)\n return signature\n },\n // Verify a timestamp signature to confirm ownership of update\n verifyTimestamp: async (timestamp, signature, publicKey, cb) => {\n if (!publicKey || !timestamp || !signature) {\n if (cb) cb(false)\n return false\n }\n\n try {\n // Convert timestamp to string for consistent hashing\n const timestampStr = timestamp.toString()\n const hash = await utils.sha256(timestampStr)\n\n const key = await utils.subtle.importKey(\n \"jwk\",\n utils.jwk(publicKey),\n {name: \"ECDSA\", namedCurve: \"P-256\"},\n false,\n [\"verify\"],\n )\n\n const sig = new Uint8Array(SafeBuffer.from(signature, \"base64\"))\n const alg = {name: \"ECDSA\", hash: {name: \"SHA-256\"}}\n\n const isValid = await utils.subtle.verify(\n alg,\n key,\n sig,\n new Uint8Array(hash),\n )\n\n if (cb) cb(isValid)\n return isValid\n } catch (err) {\n console.log(`error verifying timestamp signature: ${err.message}`)\n if (cb) cb(false)\n return false\n }\n },\n work: async (data, salt, cb) => {\n if (typeof salt === \"function\") {\n cb = salt\n salt = undefined\n }\n if (typeof salt === \"undefined\") salt = utils.random(9)\n\n const key = await utils.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(utils.stringify(data)),\n {name: \"PBKDF2\"},\n false,\n [\"deriveBits\"],\n )\n const alg = {\n name: \"PBKDF2\",\n iterations: 100000,\n salt: new TextEncoder().encode(salt),\n hash: {name: \"SHA-256\"},\n }\n const work = await utils.subtle.deriveBits(alg, key, 512)\n // Use \"pair\" format so that work can be used as epriv by decrypt.\n const pair = {epriv: SafeBuffer.from(work, \"binary\").toString(\"base64\")}\n if (cb) cb(pair)\n return pair\n },\n secret: async (to, from, cb) => {\n if (!to || !to.epub || !from || !from.epub || !from.epriv) {\n if (cb) cb(null)\n return null\n }\n\n const alg = {name: \"ECDH\", namedCurve: \"P-256\"}\n const pub = utils.jwk(to.epub)\n const pubKey = await utils.subtle.importKey(\"jwk\", pub, alg, true, [])\n const priv = utils.jwk(from.epub, from.epriv, false)\n // utils.jwk provides default key_ops but it shouldn't be used here.\n delete priv.key_ops\n const derived = await utils.subtle\n .importKey(\"jwk\", priv, alg, false, [\"deriveBits\"])\n .then(async key => {\n const derivedBits = await utils.subtle.deriveBits(\n {public: pubKey, name: \"ECDH\", namedCurve: \"P-256\"},\n key,\n 256,\n )\n const derivedKey = await utils.subtle.importKey(\n \"raw\",\n new Uint8Array(derivedBits),\n {name: \"AES-GCM\", length: 256},\n true,\n [\"encrypt\", \"decrypt\"],\n )\n return utils.subtle.exportKey(\"jwk\", derivedKey).then(({k}) => k)\n })\n // Use \"pair\" format so that secret can be used as epriv by encrypt.\n if (cb) cb({epriv: derived})\n return {epriv: derived}\n },\n}\n\nexport default SEA\n", "import * as utils from \"./utils.js\"\nimport SEA from \"./sea.js\"\n\n// Maximum number of souls to keep in memory\nconst MAX_GRAPH_SIZE = 10000\n\n// state and value are the incoming changes.\n// currentState and currentValue are the current graph data.\nconst Ham = (state, currentState, value, currentValue, signed = false) => {\n if (state < currentState) return {historical: true}\n\n if (state > currentState) return {incoming: true}\n\n // state is equal to currentState. Old data is expected to propagate through\n // the network, but conflicting values with same signed timestamp are ignored\n // since the owner can only create one value per timestamp.\n if (signed && value !== currentValue) {\n return {historical: true}\n }\n\n // Lexically compare to resolve conflict (for unsigned or matching values)\n if (typeof value !== \"string\") {\n value = JSON.stringify(value) || \"\"\n }\n if (typeof currentValue !== \"string\") {\n currentValue = JSON.stringify(currentValue) || \"\"\n }\n // No update required.\n if (value === currentValue) return {state: true}\n\n // Keep the current value.\n if (value < currentValue) return {current: true}\n\n // Otherwise update using the incoming value.\n return {incoming: true}\n}\n\nHam.mix = async (\n change,\n graph,\n hasNode,\n secure,\n listen,\n maxGraphSize = MAX_GRAPH_SIZE,\n) => {\n if (!change || typeof change !== \"object\") {\n throw new TypeError(\"change must be an object\")\n }\n if (!graph || typeof graph !== \"object\") {\n throw new TypeError(\"graph must be an object\")\n }\n if (!listen || typeof listen !== \"object\") {\n throw new TypeError(\"listen must be an object\")\n }\n\n const machine = Date.now()\n const now = {}\n const defer = {}\n const listeners = [] // Collect listeners to fire after store.put\n const validProperties = new Map() // Track valid properties per soul\n const validTimestamps = new Map() // Track valid timestamps per soul\n let wait = 0\n\n for (const soul of Object.keys(change)) {\n const node = change[soul]\n let updated = false\n let alias = false\n let nodeWait = 0\n let verify = secure\n\n if (!node || !node._) continue\n\n const pub = node[utils.userPublicKey]\n // If timestamp signatures and public key are provided then always verify\n if (node._[\"s\"] && pub) verify = true\n\n // Special case if soul starts with \"~\". Node must be system data ie,\n // ~@alias or ~publickey. For aliases, key and value must be a self\n // identifying rel. For public keys, data needs to be signed and verified.\n // (This is also true for any data when the secure flag is used.)\n if (soul.length > 1 && soul[0] === \"~\") {\n if (soul[1] === \"@\") {\n alias = true\n verify = false\n } else {\n if (pub && soul != \"~\" + pub) {\n console.log(`error public key does not match for soul: ${soul}`)\n continue\n }\n\n verify = true\n }\n }\n if (verify) {\n // Signature verification: check node._[\"s\"] which can contain:\n // 1. Per-property signatures (legacy): keys are property names\n // 2. Timestamp signatures (new): keys are numeric timestamps\n if (!pub || !node._) {\n continue\n }\n\n const signedTimestamps = new Set()\n const signedProperties = new Set()\n\n // Skip verification of timestamps that are older than what's in the graph\n // to prevent old signatures from distributed messages causing conflicts\n const incomingTimestamps = Object.entries(node._[\">\"] || {})\n\n for (const [key, sig] of Object.entries(node._[\"s\"] || {})) {\n const asNumber = Number(key)\n if (!isNaN(asNumber) && asNumber > 0) {\n // Skip verification only if ALL properties for this timestamp are\n // already newer in the graph. Using some() would incorrectly skip\n // valid updates when only one property in a batch is outdated.\n const propsForTimestamp = incomingTimestamps.filter(\n ([, ts]) => Number(ts) === asNumber,\n )\n const allNewerInGraph =\n propsForTimestamp.length > 0 &&\n propsForTimestamp.every(([prop]) => {\n const graphState =\n graph[soul] && graph[soul]._[\">\"] ? graph[soul]._[\">\"][prop] : 0\n return graphState > asNumber\n })\n\n if (allNewerInGraph) {\n continue\n }\n\n const isValid = await SEA.verifyTimestamp(asNumber, sig, pub)\n if (isValid) {\n signedTimestamps.add(asNumber)\n // Add all properties with this timestamp to signed set\n for (const [prop, ts] of incomingTimestamps) {\n if (Number(ts) === asNumber) {\n signedProperties.add(prop)\n }\n }\n }\n }\n }\n\n // If no properties verified, skip this update\n if (signedProperties.size === 0) {\n continue\n }\n\n // Track signed properties and timestamps for this soul\n validProperties.set(soul, signedProperties)\n validTimestamps.set(soul, signedTimestamps)\n }\n\n for (const key of Object.keys(node)) {\n if (key === \"_\") continue\n\n // Properties without signatures in this update are left unchanged\n if (validProperties.has(soul) && !validProperties.get(soul).has(key)) {\n continue\n }\n\n const value = node[key]\n const state = node._ && node._[\">\"] ? node._[\">\"][key] : 0\n const currentValue = (graph[soul] || {})[key]\n const currentState = (graph[soul] || {_: {\">\": {}}})._[\">\"][key] || 0\n\n if (alias && key !== utils.rel.is(value)) {\n console.log(`error alias ${alias}: ${key} !== ${utils.rel.is(value)}`)\n continue\n }\n\n // Defer the update if ahead of machine time.\n const skew = state - machine\n if (skew > 0) {\n // Ignore update if ahead by more than 24 hours.\n if (skew > 86400000) continue\n\n // Wait the shortest difference before trying the updates again.\n if (wait === 0 || skew < wait) wait = nodeWait = skew\n if (!defer[soul]) {\n defer[soul] = {_: {\"#\": soul, \">\": {}, s: {}}}\n }\n defer[soul][key] = value\n defer[soul]._[\">\"][key] = state\n if (node._[\"s\"] && node._[\"s\"][state]) {\n defer[soul]._[\"s\"][state] = node._[\"s\"][state]\n }\n } else {\n // Check if this property has a signed timestamp\n const isSigned =\n validTimestamps.has(soul) && validTimestamps.get(soul).has(state)\n const result = Ham(state, currentState, value, currentValue, isSigned)\n if (result.incoming) {\n if (!now[soul]) {\n now[soul] = {_: {\"#\": soul, \">\": {}, s: {}}}\n }\n if (!graph[soul]) {\n graph[soul] = {_: {\"#\": soul, \">\": {}, s: {}}}\n }\n graph[soul][key] = now[soul][key] = value\n graph[soul]._[\">\"][key] = now[soul]._[\">\"][key] = state\n if (node._[\"s\"] && node._[\"s\"][state]) {\n graph[soul]._[\"s\"][state] = now[soul]._[\"s\"][state] =\n node._[\"s\"][state]\n }\n // Collect event listeners to fire after store.put completes.\n // This ensures listeners always fire with data that's been stored.\n if (listen[soul]) {\n listen[soul]\n .filter(l => utils.match(l[\".\"], key))\n .forEach(l => listeners.push(l.cb))\n }\n updated = true\n }\n }\n }\n\n // Collect event listeners for update on soul.\n if (updated && listen[soul]) {\n listen[soul]\n .filter(l => utils.match(l[\".\"]))\n .forEach(l => listeners.push(l.cb))\n }\n }\n\n const souls = Object.keys(graph)\n if (souls.length > maxGraphSize) {\n // Sort by oldest state timestamp and remove oldest entries\n const soulsByAge = souls\n .map(soul => {\n const states = graph[soul]._ && graph[soul]._[\">\"]\n const maxState = states ? Math.max(...Object.values(states)) : 0\n return {soul, maxState}\n })\n .sort((a, b) => a.maxState - b.maxState)\n const remove = soulsByAge.slice(0, souls.length - maxGraphSize)\n remove.forEach(({soul}) => {\n delete graph[soul]\n if (hasNode) hasNode.delete(soul)\n })\n }\n\n return {now: now, defer: defer, wait: wait, listeners: listeners}\n}\n\nexport default Ham\n", "import * as utils from \"./utils.js\"\n\n// ASCII character for group separator.\nconst group = String.fromCharCode(29)\n// ASCII character for record separator.\nconst record = String.fromCharCode(30)\n\nconst Radix = () => {\n const radix = (keys, value, tree) => {\n if (!tree) {\n if (!radix[group]) radix[group] = {}\n tree = radix[group]\n }\n if (!keys) return tree\n\n let i = 0\n let tmp = {}\n let key = keys[i]\n const max = keys.length - 1\n const noValue = typeof value === \"undefined\"\n // Find a matching value using the shortest string from keys.\n let found = tree[key]\n while (!found && i < max) {\n key += keys[++i]\n found = tree[key]\n }\n\n if (!found) {\n if (noValue) {\n // If not found from the provided keys try matching with an existing\n // key.\n const result = utils.obj.map(tree, (hasValue, hasKey) => {\n let j = 0\n let matchingKey = \"\"\n while (hasKey[j] === keys[j]) {\n matchingKey += hasKey[j++]\n }\n if (matchingKey) {\n // matchingKey has to be as long as the original keys when\n // reading.\n if (j <= max) return\n\n tmp[hasKey.slice(j)] = hasValue\n return hasValue\n }\n })\n if (!result) return\n\n return tmp\n }\n\n // Writing: find the EXISTING key with the longest shared prefix,\n // not just the first one with any overlap at all (obj.map stops at\n // the first non-undefined result, so a plain find here would settle\n // for whichever candidate happens to come first in Object.keys'\n // own iteration order). A radix tree's own invariant - no two\n // sibling keys share a prefix - only holds if every insertion\n // merges with its one true match; with many keys sharing this tree\n // at once (many concurrent writers batched together), a\n // coincidentally shorter, unrelated key can otherwise \"win\" over\n // the real, much longer match - silently misplacing the new key\n // under the wrong group, while its actual sibling is never touched\n // at all and stays wherever it already was, invisible to any read\n // that expects it inside this new group.\n let bestKey = null\n let bestMatch = \"\"\n for (const hasKey of Object.keys(tree)) {\n let j = 0\n let matchingKey = \"\"\n while (hasKey[j] === keys[j]) {\n matchingKey += hasKey[j++]\n }\n if (matchingKey.length > bestMatch.length) {\n bestKey = hasKey\n bestMatch = matchingKey\n }\n }\n\n if (bestKey) {\n const hasValue = tree[bestKey]\n const j = bestMatch.length\n let replace = {\n [bestKey.slice(j)]: hasValue,\n [keys.slice(j)]: {[record]: value},\n }\n tree[bestMatch] = {[group]: replace}\n delete tree[bestKey]\n } else {\n if (!tree[key]) tree[key] = {}\n tree[key][record] = value\n }\n } else if (i === max) {\n // If no value use the key provided to return a whole group or record.\n if (noValue) {\n // If an individual record isn't found then return the whole group.\n return typeof found[record] === \"undefined\"\n ? found[group]\n : found[record]\n }\n // Otherwise create a new record at the provided key for value.\n found[record] = value\n } else {\n // Found at a shorter key, try again.\n if (!found[group] && !noValue) found[group] = {}\n return radix(keys.slice(++i), value, found[group])\n }\n }\n return radix\n}\n\nRadix.map = function map(radix, cb, opt, pre) {\n if (!pre) pre = []\n var tree = radix[group] || radix\n var keys = Object.keys(tree).sort()\n var u\n\n for (let i = 0; i < keys.length; i++) {\n let key = keys[i]\n let found = tree[key]\n let tmp = found[record]\n if (typeof tmp !== \"undefined\") {\n tmp = cb(tmp, pre.join(\"\") + key, key, pre)\n if (typeof tmp !== \"undefined\") return tmp\n } else if (opt) {\n cb(u, pre.join(\"\"), key, pre)\n }\n if (found[group]) {\n pre.push(key)\n tmp = map(found[group], cb, opt, pre)\n if (typeof tmp !== \"undefined\") return tmp\n pre.pop()\n }\n }\n}\n\nexport default Radix\n", "import Radix from \"./radix.js\"\nimport * as utils from \"./utils.js\"\n\n// ASCII character for end of text\nconst etx = String.fromCharCode(3)\n// ASCII character for enquiry\nconst enq = String.fromCharCode(5)\n// ASCII character for unit separator\nconst unit = String.fromCharCode(31)\n\n// Radisk provides access to a radix tree that is stored in the provided\n// opt.store interface\nconst Radisk = opt => {\n var u\n\n // Multi-file cache for all parsed radix trees\n const cache = new Map()\n // File listing cache to avoid repeated directory scans\n let fileListCache = null\n let fileListCacheTime = 0\n const FILE_LIST_CACHE_TTL = 10000 // 10 seconds\n // Pending reads queue to avoid duplicate reads for the same key\n const pendingReads = new Map()\n\n // Memory monitoring and cleanup\n let lastMemoryCheck = 0\n const MEMORY_CHECK_INTERVAL = 30000 // Check every 30 seconds\n const HEAP_WARNING_THRESHOLD = 0.8 // Warn at 80% of max heap size\n const HEAP_CLEANUP_THRESHOLD = 0.9 // Clean cache at 90% of max heap size\n\n if (!opt) opt = {}\n if (!opt.log) opt.log = console.log\n if (!opt.batch) opt.batch = 100 // Balanced batch size for performance\n if (!opt.write) opt.write = 1 // Wait time before write in milliseconds\n if (!opt.size) opt.size = 1024 * 1024 // File size on disk, default 1MB\n if (!opt.memoryLimit) opt.memoryLimit = 500 // Memory limit in MB\n if (typeof opt.cache === \"undefined\") opt.cache = true // Used in tests\n\n if (!opt.store) {\n opt.log(\n \"Radisk needs `store` interface with `{get: fn, put: fn, list: fn}`\",\n )\n return\n }\n if (!opt.store.get) {\n opt.log(\"Radisk needs `store.get` interface with `(file, cb)`\")\n return\n }\n if (!opt.store.put) {\n opt.log(\"Radisk needs `store.put` interface with `(file, data, cb)`\")\n return\n }\n if (!opt.store.list) {\n opt.log(\"Radisk needs a streaming `store.list` interface with `(cb)`\")\n return\n }\n\n // Memory monitoring and cache cleanup\n const checkMemoryUsage = () => {\n if (typeof process === \"undefined\" || !process.memoryUsage) return\n\n const now = Date.now()\n if (now - lastMemoryCheck < MEMORY_CHECK_INTERVAL) return\n lastMemoryCheck = now\n\n const memUsage = process.memoryUsage()\n const heapUsed = memUsage.heapUsed\n const heapTotal = memUsage.heapTotal\n const maxHeapSize = opt.memoryLimit * 1024 * 1024\n const heapUsageRatio = heapUsed / maxHeapSize\n\n if (heapUsageRatio > HEAP_CLEANUP_THRESHOLD) {\n const cacheSize = cache.size\n console.log(\n `[RADISK-MEMORY] High memory usage: ${Math.round(heapUsageRatio * 100)}% of heap limit. Clearing ${cacheSize} cached files.`,\n )\n cache.clear()\n // Force garbage collection if available\n if (global.gc) {\n global.gc()\n }\n // Reset timer to avoid immediate re-check until GC has time to work\n lastMemoryCheck = now + MEMORY_CHECK_INTERVAL\n } else if (heapUsageRatio > HEAP_WARNING_THRESHOLD) {\n console.log(\n `[RADISK-MEMORY] Memory warning: ${Math.round(heapUsageRatio * 100)}% of heap limit used. Cache size: ${cache.size} files.`,\n )\n }\n }\n\n // Any and all storage adapters should:\n // 1. Because writing to disk takes time, we should batch data to disk.\n // This improves performance, and reduces potential disk corruption.\n // 2. If a batch exceeds a certain number of writes, we should immediately\n // write to disk when physically possible. This caps total performance,\n // but reduces potential loss.\n const radisk = (key, value, cb) => {\n key = \"\" + key\n\n // If no value is provided then the second parameter is the callback\n // function. Read value from memory or disk and call callback with it.\n if (typeof value === \"function\") {\n cb = value\n value = radisk.batch(key)\n if (typeof value !== \"undefined\") {\n return cb(u, value)\n }\n\n if (radisk.thrash.at) {\n value = radisk.thrash.at(key)\n if (typeof value !== \"undefined\") {\n return cb(u, value)\n }\n }\n\n if (pendingReads.has(key)) {\n pendingReads.get(key).push(cb)\n return\n }\n\n pendingReads.set(key, [cb])\n // If radisk.read genuinely hangs (fd leak, stuck I/O), recover\n // callbacks as a cache miss so callers can fall through to the wire path.\n // 30s is long enough to distinguish a hang from a slow-but-healthy read.\n const timeout = setTimeout(() => {\n const callbacks = pendingReads.get(key)\n if (!callbacks) return\n opt.log(`radisk read hang detected for key: ${key}`)\n pendingReads.delete(key)\n callbacks.forEach(callback => callback(null, null))\n }, 30000)\n return radisk.read(key, (err, result) => {\n clearTimeout(timeout)\n const callbacks = pendingReads.get(key) || []\n pendingReads.delete(key)\n callbacks.forEach(callback => callback(err, result))\n })\n }\n\n // Otherwise store the value provided.\n radisk.batch(key, value)\n // Check memory usage after writing to in-memory radix tree\n checkMemoryUsage()\n if (cb) {\n radisk.batch.acks.push(cb)\n }\n // Don't wait if we have batched too many.\n if (++radisk.batch.ed >= opt.batch) {\n return radisk.thrash()\n }\n\n // Otherwise wait for more updates before writing.\n clearTimeout(radisk.batch.timeout)\n radisk.batch.timeout = setTimeout(radisk.thrash, opt.write)\n }\n\n radisk.batch = Radix()\n radisk.batch.acks = []\n radisk.batch.ed = 0\n\n radisk.thrash = () => {\n if (radisk.thrash.ing) {\n return (radisk.thrash.more = true)\n }\n\n clearTimeout(radisk.batch.timeout)\n radisk.thrash.more = false\n radisk.thrash.ing = true\n var batch = (radisk.thrash.at = radisk.batch)\n radisk.batch = null\n radisk.batch = Radix()\n radisk.batch.acks = []\n radisk.batch.ed = 0\n radisk.save(batch, err => {\n if (err) opt.log(err)\n batch.acks.forEach(cb => cb(err))\n radisk.thrash.at = null\n radisk.thrash.ing = false\n if (radisk.thrash.more) radisk.thrash()\n })\n }\n\n // 1. Find the first radix item in memory\n // 2. Use that as the starting index in the directory of files\n // 3. Find the first file that is lexically larger than it\n // 4. Read the previous file into memory\n // 5. Scan through in memory radix for all values lexically less than limit\n // 6. Merge and write all of those to the in-memory file and back to disk\n radisk.save = (rad, cb) => {\n const save = {\n find: (tree, key) => {\n // This is false for any key until save.start is set to an initial key.\n if (key < save.start) return\n\n save.start = key\n // store.list's own streamed order isn't guaranteed to be sorted -\n // fs.readdir in particular makes no such promise, unlike\n // radisk.read's own file lookup, which already sorts before\n // searching. Collect the full list and sort it first, rather\n // than scanning the raw stream as it arrives, since save.lex's\n // own boundary search below only works correctly over genuinely\n // sorted input - fed an unsorted stream, it can match the wrong\n // file, or stop tracking new candidates the moment the stream\n // stops looking monotonic, silently losing track of files that\n // arrive afterward.\n const files = []\n opt.store.list(file => {\n if (file) {\n files.push(file)\n return\n }\n files.sort()\n save.lex(files)\n })\n return true\n },\n lex: files => {\n // save.start can be set to undefined by a previous call to\n // save.mix, so don't continue in this case.\n if (!save.start) return\n\n let candidate = null\n for (const file of files) {\n if (file > save.start) {\n // ! is used as the first file name as it's the first\n // printable character, so always matches as lexically less\n // than any node.\n save.mix(candidate || \"!\", save.start, file)\n return\n }\n candidate = file\n }\n save.mix(candidate || \"!\", save.start, u)\n },\n mix: (file, start, end) => {\n save.start = u\n // Use cache if available, otherwise parse from disk\n if (cache.has(file)) {\n const disk = cache.get(file)\n Radix.map(rad, (value, key) => {\n if (key < start) return\n\n if (end && end < key) {\n // Found where the next file segment starts - stop here (the\n // non-undefined return is what actually stops Radix.map's\n // own iteration). Without it, the scan kept going through\n // every remaining entry in the whole batch, each one\n // overwriting save.start in turn, so save.next's own resume\n // point ended up as the LAST key in the batch rather than\n // the very next one - silently skipping every entry in\n // between as \"already processed\" when none of them ever\n // were.\n save.start = key\n return true\n }\n\n disk(key, value)\n })\n radisk.write(file, disk, save.next)\n } else {\n radisk.parse(file, (err, disk) => {\n if (err) return cb(err)\n\n Radix.map(rad, (value, key) => {\n if (key < start) return\n\n if (end && end < key) {\n save.start = key\n return true\n }\n\n disk(key, value)\n })\n // Populate the cache with this merge synchronously, before the\n // async store.put below even starts - a write's own merged\n // result is always authoritative (it's this batch's actual\n // content), unlike a plain read's parse, which can't tell\n // whether it raced ahead of a write. Closes the window where a\n // concurrent read's own parse-from-disk (started before this\n // write, resolving after it) would otherwise be free to\n // populate the cache with stale, pre-write data - see\n // radisk.read's own matching change below.\n if (opt.cache) cache.set(file, disk)\n radisk.write(file, disk, save.next)\n })\n }\n },\n next: err => {\n if (err) return cb(err)\n\n if (save.start) return Radix.map(rad, save.find)\n\n cb(err)\n },\n }\n Radix.map(rad, save.find)\n }\n\n radisk.write = (file, rad, cb) => {\n // A split produces two independent opt.store.put calls - this file's\n // own (truncated) remainder below, and the recursive call for the\n // split-off sub-file. pending starts at 1 for this file's own write,\n // and is bumped to 2 the moment a split is decided, so cb only fires\n // once both halves are actually durable - calling it as soon as\n // whichever one finishes first (the previous behavior) let a caller\n // continue - including resolving the original put()'s own callback -\n // before the other half's data had actually been written.\n let pending = 1\n let firstErr = null\n const settle = err => {\n if (err && !firstErr) firstErr = err\n if (--pending > 0) return\n cb(firstErr)\n }\n const write = {\n text: \"\",\n limit: \"\",\n done: false,\n count: 0,\n halfKey: \"\", // soul ID at the ~opt.size/2 mark for a balanced split\n halfOffset: 0, // write.text.length before that entry\n each: (value, key, k, pre) => {\n // each is called for all keys, but stop adding to write.text when\n // write.slice is called, then the current contents of write.text\n // will be written to file.\n if (write.done) return\n\n write.count++\n value = typeof value === \"undefined\" ? \"\" : \"=\" + Radisk.encode(value)\n const enc =\n Radisk.encode(pre.length) + \"#\" + Radisk.encode(k) + value + \"\\n\"\n // Cannot split the file if only have one entry to write. Allow splitting\n // at depth > 0 only when k itself contains enq, meaning k is a full\n // \"soulId\\x05property\" key, not merely a property suffix of a shared\n // soul prefix. Use the full key (pre + k) to extract the soul boundary.\n const validBoundary =\n pre.length === 0 || (pre.length === 1 && k.includes(enq))\n\n // Record the first valid split boundary past the halfway mark so a\n // full overflow can split here instead of at the tail, keeping both\n // halves near opt.size/2 rather than leaving the file always full.\n if (\n !write.halfKey &&\n write.count > 1 &&\n write.text.length > opt.size / 2 &&\n validBoundary\n ) {\n const fullKey = pre.join(\"\") + k\n const end = fullKey.indexOf(enq)\n write.halfKey = end === -1 ? fullKey : fullKey.substring(0, end)\n write.halfOffset = write.text.length\n }\n\n if (\n write.count > 1 &&\n write.text.length + enc.length > opt.size &&\n validBoundary\n ) {\n const fullKey = pre.join(\"\") + k\n const end = fullKey.indexOf(enq)\n write.limit =\n write.halfKey || (end === -1 ? fullKey : fullKey.substring(0, end))\n // Cannot split if the key is the same as the current file name.\n if (write.limit !== file) {\n // Truncate to the balanced split point \u2014 text after halfOffset is\n // handled by the write.slice call below, which reads from rad.\n if (write.halfKey) {\n write.text = write.text.substring(0, write.halfOffset)\n }\n write.done = true\n write.sub = Radix()\n Radix.map(rad, write.slice)\n pending++\n radisk.write(write.limit, write.sub, settle)\n return\n }\n }\n\n write.text += enc\n },\n slice: (value, key) => {\n if (key < write.limit) return\n\n write.sub(key, value)\n },\n }\n Radix.map(rad, write.each, true)\n // There is always accumulated write.text to store once write.each has\n // finished.\n opt.store.put(file, write.text, err => {\n // If a split occurred the cached radix tree still contains entries that\n // were moved to the sub-file. Invalidate so the next save.mix re-reads\n // from disk rather than re-writing those entries back to this file.\n if (write.done) {\n cache.delete(file)\n fileListCache = null\n }\n settle(err)\n })\n }\n\n radisk.read = (key, cb) => {\n // Only the soul of the key is compared to filenames (see radisk.write).\n const end = key.indexOf(enq)\n const soul = end === -1 ? key : key.substring(0, end)\n\n // Binary search for largest filename <= soul in a sorted array.\n const findFile = files => {\n let lo = 0,\n hi = files.length - 1,\n result = null\n while (lo <= hi) {\n const mid = (lo + hi) >> 1\n if (files[mid] <= soul) {\n result = files[mid]\n lo = mid + 1\n } else {\n hi = mid - 1\n }\n }\n return result\n }\n\n const read = file => {\n if (!file) {\n cb(\"no file found\", u)\n return\n }\n if (opt.cache && cache.has(file)) {\n return cb(u, cache.get(file)(key))\n }\n radisk.parse(file, (err, disk) => {\n if (err) opt.log(err)\n // Never overwrite an existing cache entry from a plain read - it\n // can't tell whether it raced ahead of a concurrent write (started\n // before that write, but resolving after the write already\n // installed its own authoritative, freshly-merged entry - see\n // save.mix's own matching change). Only populate the cache when\n // nothing beat this read to it.\n if (disk && opt.cache && !cache.has(file)) {\n cache.set(file, disk)\n checkMemoryUsage()\n }\n cb(err, disk ? disk(key) : u)\n })\n }\n\n const now = Date.now()\n if (\n opt.cache &&\n fileListCache &&\n now - fileListCacheTime < FILE_LIST_CACHE_TTL\n ) {\n read(findFile(fileListCache, soul))\n } else {\n const files = []\n opt.store.list(file => {\n if (file) {\n files.push(file)\n return\n }\n files.sort()\n if (opt.cache) {\n fileListCache = files\n fileListCacheTime = now\n }\n read(findFile(files, soul))\n })\n }\n }\n\n // Let us start by assuming we are the only process that is\n // changing the directory or bucket. Not because we do not want\n // to be multi-process/machine, but because we want to experiment\n // with how much performance and scale we can get out of only one.\n // Then we can work on the harder problem of being multi-process.\n radisk.parse = (file, cb) => {\n const parse = {\n disk: Radix(),\n read: (err, data) => {\n if (err) return cb(err)\n\n if (!data) return cb(u, parse.disk)\n\n let pre = []\n let preString = \"\"\n // Work though data by splitting into 3 values. The first value says\n // if the second value is one of: the radix level for a key, the key\n // iteself, or a value. The third is the rest of the data to work with.\n let tmp = parse.split(data)\n while (tmp) {\n let key\n let value\n let i = tmp[1]\n tmp = parse.split(tmp[2]) || \"\"\n if (tmp[0] === \"#\") {\n key = tmp[1]\n // Optimize prefix building - avoid repeated joins\n if (i < pre.length) {\n pre.length = i\n }\n if (i <= pre.length) {\n pre[i] = key\n pre.length = i + 1\n }\n // Only rebuild preString when prefix changes\n preString = pre.join(\"\")\n }\n tmp = parse.split(tmp[2]) || \"\"\n if (tmp[0] === \"\\n\") continue\n\n if (tmp[0] === \"=\") value = tmp[1]\n if (typeof key !== \"undefined\" && typeof value !== \"undefined\") {\n parse.disk(preString, value)\n }\n tmp = parse.split(tmp[2])\n }\n cb(u, parse.disk)\n },\n split: data => {\n if (!data) return\n\n const i = data.indexOf(unit)\n if (i === -1) return\n\n const a = data.slice(0, i)\n let o = {}\n return [a, Radisk.decode(data.slice(i), o), data.slice(i + o.i)]\n },\n }\n opt.store.get(file, parse.read)\n }\n\n return radisk\n}\n\nRadisk.encode = data => {\n // A key should be passed in as a string to encode, a value can optionally be\n // an array of 2-3 items: [value, state] or [value, state, signature].\n let state = \"\"\n let sig = \"\"\n if (data instanceof Array && (data.length === 2 || data.length === 3)) {\n state = etx + data[1]\n if (data.length === 3 && data[2]) {\n sig = etx + data[2]\n }\n data = data[0]\n }\n\n if (typeof data === \"string\") {\n let i = 0\n let current = null\n let text = unit\n while ((current = data[i++])) {\n if (current === unit) text += unit\n }\n return text + '\"' + data + state + sig + unit\n }\n\n const rel = utils.rel.is(data)\n if (rel) return unit + \"#\" + rel + state + sig + unit\n\n if (utils.num.is(data)) return unit + \"+\" + (data || 0) + state + sig + unit\n\n if (data === true) return unit + \"+\" + state + sig + unit\n\n if (data === false) return unit + \"-\" + state + sig + unit\n\n if (data === null) return unit + \" \" + state + sig + unit\n}\n\nRadisk.decode = (data, obj) => {\n var i = -1\n var n = 0\n var current = null\n var previous = null\n var textStart = -1\n var textEnd = -1\n if (data[0] !== unit) return\n\n // Find a control character previous to the text we want, skipping\n // consecutive unit separator characters at the beginning of the data.\n while ((current = data[++i])) {\n if (previous) {\n if (textStart === -1) textStart = i\n if (current === unit) {\n if (--n <= 0) {\n textEnd = i\n break\n }\n }\n } else if (current === unit) {\n n++\n } else {\n previous = current || true\n }\n }\n\n const text =\n textStart !== -1 ? data.slice(textStart, textEnd !== -1 ? textEnd : i) : \"\"\n\n if (obj) obj.i = i + 1\n\n let parts = text.split(etx)\n let value = parts[0]\n let state = parts[1]\n let sig = parts[2]\n\n if (!state) {\n if (previous === '\"') return text\n\n if (previous === \"#\") return utils.rel.ify(text)\n\n if (previous === \"+\") {\n if (text.length === 0) return true\n\n return parseFloat(text)\n }\n\n if (previous === \"-\") return false\n\n if (previous === \" \") return null\n } else {\n state = parseFloat(state)\n // If state was found then return an array with [value, state] or [value, state, sig]\n if (sig) {\n if (previous === '\"') return [value, state, sig]\n\n if (previous === \"#\") return [utils.rel.ify(value), state, sig]\n\n if (previous === \"+\") {\n if (value.length === 0) return [true, state, sig]\n\n return [parseFloat(value), state, sig]\n }\n\n if (previous === \"-\") return [false, state, sig]\n\n if (previous === \" \") return [null, state, sig]\n } else {\n if (previous === '\"') return [value, state]\n\n if (previous === \"#\") return [utils.rel.ify(value), state]\n\n if (previous === \"+\") {\n if (value.length === 0) return [true, state]\n\n return [parseFloat(value), state]\n }\n\n if (previous === \"-\") return [false, state]\n\n if (previous === \" \") return [null, state]\n }\n }\n}\n\nexport default Radisk\n", "import Radisk from \"./radisk.js\"\nimport Radix from \"./radix.js\"\nimport * as utils from \"./utils.js\"\n\nconst isNode = typeof process !== \"undefined\" && process.versions?.node != null\nconst fs = isNode ? await import(/*webpackIgnore: true*/ \"node:fs\") : undefined\n\n// ASCII character for enquiry.\nconst enq = String.fromCharCode(5)\n// ASCII character for unit separator.\nconst unit = String.fromCharCode(31)\n// On-disk root node format.\nconst root = unit + \"+0\" + unit + \"#\" + unit + '\"root' + unit\n\nconst fileSystem = opt => {\n const dir = opt.file\n\n if (isNode) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir)\n if (!fs.existsSync(dir + \"/!\")) fs.writeFileSync(dir + \"/!\", root)\n\n return {\n get: (file, cb) => {\n fs.readFile(dir + \"/\" + file, (err, data) => {\n if (err) {\n if (err.code === \"ENOENT\") {\n cb()\n return\n }\n\n console.log(\"fs.readFile error:\", err)\n }\n if (data) data = data.toString()\n cb(err, data)\n })\n },\n put: (file, data, cb) => {\n // Don't put tmp files under dir so that they're not listed.\n var tmp = file + \".\" + utils.text.random(9) + \".tmp\"\n fs.writeFile(tmp, data, err => {\n if (err) {\n console.log(\"fs.writeFile error:\", err)\n cb(err)\n return\n }\n\n fs.rename(tmp, dir + \"/\" + file, cb)\n })\n },\n list: cb => {\n fs.readdir(dir, (err, files) => {\n if (err) {\n console.log(\"fs.readdir error:\", err)\n cb()\n return\n }\n\n files.forEach(cb)\n cb()\n })\n },\n }\n }\n\n if (opt.indexedDB) {\n let db\n const dbReady = new Promise((resolve, reject) => {\n const o = indexedDB.open(dir, 1)\n o.onupgradeneeded = event => {\n event.target.result.createObjectStore(dir)\n }\n o.onerror = event => {\n console.log(event)\n reject(event)\n }\n o.onsuccess = () => {\n db = o.result\n // Create the root node if it doesn't exist.\n if (db) {\n const tx = db.transaction([dir], \"readonly\")\n const req = tx.objectStore(dir).getKey(\"!\")\n req.onerror = () => {\n console.log(`error getting key ${dir}/!`)\n reject(req.error)\n }\n req.onsuccess = () => {\n if (!req.result) {\n const tx = db.transaction([dir], \"readwrite\")\n const req = tx.objectStore(dir).put(root, \"!\")\n req.onerror = () => {\n console.log(`error putting root on ${dir}/!`)\n reject(req.error)\n }\n req.onsuccess = () => {\n resolve()\n }\n } else {\n resolve()\n }\n }\n } else {\n console.log(\"error indexedDB not available\")\n reject(new Error(\"indexedDB not available\"))\n }\n }\n })\n\n return {\n get: (file, cb) => {\n const _get = (file, cb) => {\n const tx = db.transaction([dir], \"readonly\")\n const req = tx.objectStore(dir).get(file)\n req.onerror = () => {\n console.log(`error getting ${dir}/${file}`)\n cb(req.error)\n }\n req.onsuccess = () => {\n cb(null, req.result)\n }\n }\n\n dbReady\n .then(() => {\n _get(file, cb)\n })\n .catch(err => {\n cb(err)\n })\n },\n put: (file, data, cb) => {\n const _put = (file, data, cb) => {\n const tx = db.transaction([dir], \"readwrite\")\n const req = tx.objectStore(dir).put(data, file)\n req.onerror = () => {\n console.log(`error putting data on ${dir}/${file}`)\n cb(req.error)\n }\n req.onsuccess = () => {\n cb(null)\n }\n }\n\n dbReady\n .then(() => {\n _put(file, data, cb)\n })\n .catch(err => {\n cb(err)\n })\n },\n list: cb => {\n const _list = cb => {\n const tx = db.transaction([dir], \"readonly\")\n const req = tx.objectStore(dir).getAllKeys()\n req.onerror = () => {\n console.log(\"error getting keys for\", dir)\n cb()\n }\n req.onsuccess = () => {\n req.result.forEach(cb)\n cb()\n }\n }\n\n dbReady\n .then(() => {\n _list(cb)\n })\n .catch(err => {\n console.log(\"error indexedDB not available:\", err)\n cb()\n })\n },\n }\n }\n\n // No browser storage.\n return {\n get: (file, cb) => {\n cb(null, root)\n },\n put: (file, data, cb) => {\n cb(null)\n },\n list: cb => {\n cb(\"!\")\n cb()\n },\n }\n}\n\n// Store provides get and put methods that can access radisk.\nconst Store = opt => {\n if (!utils.obj.is(opt)) opt = {}\n opt.file = String(opt.file || \"radata\")\n if (!opt.store) opt.store = fileSystem(opt)\n const radisk = Radisk(opt)\n\n return {\n get: (lex, cb) => {\n if (!lex || !utils.obj.is(lex)) {\n cb(\"lex required\")\n return\n }\n if (!lex[\"#\"]) {\n cb(\"soul required in lex\")\n return\n }\n\n var soul = lex[\"#\"]\n var key = typeof lex[\".\"] === \"string\" ? lex[\".\"] : \"\"\n var node\n var signatures = {}\n const each = (value, k) => {\n if (k !== utils.userPublicKey && !utils.match(lex[\".\"], k)) return\n\n if (!node) node = {_: {\"#\": soul, \">\": {}}}\n node[k] = value[0]\n node._[\">\"][k] = value[1]\n // If signature is present, store it in _[\"s\"]\n if (value.length === 3 && value[2]) {\n signatures[value[1]] = value[2]\n }\n }\n\n // When doing a targeted property lookup, also fetch userPublicKey in\n // parallel so ham.js can verify signatures regardless of secure mode.\n // Full-soul scans (key=\"\") already surface it via Radix.map.\n const needsPubKey = key !== \"\" && key !== utils.userPublicKey\n let pending = needsPubKey ? 2 : 1\n let cbErr = null\n const finish = err => {\n if (err && !cbErr) cbErr = err\n if (--pending > 0) return\n const graph = {[soul]: node}\n if (node && Object.keys(signatures).length > 0) {\n node._[\"s\"] = signatures\n }\n cb(cbErr, graph)\n }\n\n radisk(soul + enq + key, (err, value) => {\n if (utils.obj.is(value)) {\n Radix.map(value, each)\n if (!node) each(value, key)\n } else if (value) {\n each(value, key)\n }\n finish(err)\n })\n\n if (needsPubKey) {\n radisk(soul + enq + utils.userPublicKey, (err, value) => {\n if (value && !utils.obj.is(value)) each(value, utils.userPublicKey)\n finish(err)\n })\n }\n },\n put: (graph, cb) => {\n if (!graph) {\n cb(\"graph required\")\n return\n }\n\n let count = 0\n let finished = false\n const ack = err => {\n count--\n if (finished) return\n\n if (err) {\n finished = true\n cb(err)\n return\n }\n\n if (count === 0) {\n finished = true\n cb(null)\n }\n }\n\n Object.keys(graph).forEach(soul => {\n var node = graph[soul]\n Object.keys(node).forEach(key => {\n if (key === \"_\") return\n\n count++\n let value = node[key]\n let state = node._[\">\"][key]\n let sig = node._[\"s\"] && node._[\"s\"][state]\n let data = sig ? [value, state, sig] : [value, state]\n radisk(soul + enq + key, data, ack)\n })\n })\n },\n }\n}\n\nexport {fileSystem}\nexport default Store\n", "import Dup from \"./dup.js\"\nimport Get from \"./get.js\"\nimport Ham from \"./ham.js\"\nimport Store from \"./store.js\"\nimport * as utils from \"./utils.js\"\n\nconst isNode = typeof process !== \"undefined\" && process.versions?.node != null\n\nconst wsModule = isNode ? await import(\"ws\") : undefined\nconst fs = isNode ? await import(/*webpackIgnore: true*/ \"node:fs\") : undefined\n\nif (typeof globalThis.WebSocket === \"undefined\") {\n globalThis.WebSocket = wsModule?.WebSocket\n}\n\n// Rate limiting with throttling\nconst createRateLimiter = isTestEnv => {\n const clients = new Map()\n const maxRequests = 1500 // requests per minute\n const windowMs = 60000 // 1 minute window\n const disconnectThreshold = 10 // Disconnect after 10 violations\n let cleanupInterval = null\n\n const cleanup = () => {\n const now = Date.now()\n for (const [clientId, data] of clients.entries()) {\n if (now - data.lastCleanup > windowMs) {\n data.requests = []\n data.lastCleanup = now\n }\n data.requests = data.requests.filter(time => now - time < windowMs)\n // Reset throttle counts periodically\n if (now - data.lastCleanup > windowMs * 10) {\n data.throttleCount = 0\n }\n }\n }\n\n if (!isTestEnv) {\n cleanupInterval = setInterval(cleanup, windowMs / 4)\n }\n\n return {\n getDelay: clientId => {\n const now = Date.now()\n const client = clients.get(clientId) || {\n requests: [],\n lastCleanup: now,\n throttleCount: 0,\n }\n\n // Filter old requests\n client.requests = client.requests.filter(time => now - time < windowMs)\n\n if (client.requests.length >= maxRequests) {\n // Calculate delay based on oldest request that will expire\n const oldestRequest = Math.min(...client.requests)\n const delay = windowMs - (now - oldestRequest)\n // Increment throttle count and update client data\n client.throttleCount = (client.throttleCount || 0) + 1\n clients.set(clientId, client)\n return Math.max(0, delay)\n }\n\n // No delay needed, track this request\n client.requests.push(now)\n clients.set(clientId, client)\n return 0\n },\n\n getRemainingRequests: clientId => {\n const client = clients.get(clientId)\n if (!client) return maxRequests\n\n const now = Date.now()\n const validRequests = client.requests.filter(\n time => now - time < windowMs,\n )\n return Math.max(0, maxRequests - validRequests.length)\n },\n\n getThrottleCount: clientId => {\n const client = clients.get(clientId)\n return client ? client.throttleCount || 0 : 0\n },\n\n shouldDisconnect: clientId => {\n const client = clients.get(clientId)\n if (!client) return false\n return client.throttleCount >= disconnectThreshold\n },\n\n destroy: () => {\n if (cleanupInterval) {\n clearInterval(cleanupInterval)\n cleanupInterval = null\n }\n clients.clear()\n },\n }\n}\n\n// Safe JSON parser with size limit\nconst safeJSONParse = (data, maxSize = 1024 * 1024) => {\n try {\n if (typeof data === \"string\" && data.length > maxSize) {\n throw new Error(\"Message too large\")\n }\n return {success: true, data: JSON.parse(data)}\n } catch (error) {\n return {success: false, error: error.message}\n }\n}\n\n// Message size validator\nconst validateMessage = (data, maxSize = 1024 * 1024) => {\n // 1MB default\n if (typeof data === \"string\" && data.length > maxSize) {\n return {valid: false, error: \"Message too large\"}\n }\n if (Buffer.isBuffer(data) && data.length > maxSize) {\n return {valid: false, error: \"Message too large\"}\n }\n return {valid: true}\n}\n\n// Connection manager to limit concurrent connections\nconst createConnectionManager = (maxConnections = 1000) => {\n const connections = new Set()\n\n return {\n add: ws => {\n if (connections.size >= maxConnections) {\n return false\n }\n connections.add(ws)\n\n // Clean up on close\n const originalClose = ws.close\n ws.close = (...args) => {\n connections.delete(ws)\n return originalClose.apply(ws, args)\n }\n\n return true\n },\n\n remove: ws => {\n connections.delete(ws)\n },\n\n count: () => connections.size,\n\n isFull: () => connections.size >= maxConnections,\n }\n}\n\n// Enhanced retry mechanism with exponential backoff\nconst createRetryHandler = (maxRetries = 5) => {\n let retryCount = 0\n\n return {\n shouldRetry: () => retryCount < maxRetries,\n getDelay: () => Math.min(1000 * Math.pow(2, retryCount), 30000), // Max 30s\n increment: () => retryCount++,\n reset: () => (retryCount = 0),\n }\n}\n\n// Wire starts a websocket client or server and returns get and put methods\n// for access to the wire spec and storage.\nconst Wire = opt => {\n const dup = Dup()\n const store = Store(opt)\n const graph = {}\n const queue = {}\n const listen = {}\n // Tracks souls that have had a complete full-node store fetch, so subsequent\n // full-node requests can read directly from the in-memory graph without a\n // redundant store round-trip. Kept in sync with graph eviction via Ham.mix.\n const hasNode = new Set()\n\n // Track references we want but don't have yet\n const pendingReferences = new Set()\n\n // Debounce client-side wire update checks: skip if the same lex was checked\n // recently. Keyed by \"soul\" or \"soul.property\".\n const recentChecks = new Map()\n const recentCheckTTL = 10000 // 10 seconds\n\n // Track pending timeouts that should start when message is sent\n const pendingTimeouts = new Map()\n\n // Track offline null-response timeouts so they can be cancelled if the WS\n // connects before they fire. Keyed by the same trackId as pendingTimeouts.\n const offlineTimeouts = new Map()\n\n // Helper to check if we have a soul in memory or storage\n const hasSoul = async soul => {\n if (graph[soul]) return true\n return new Promise(resolve => {\n store.get({\"#\": soul}, (err, data) => {\n resolve(!err && data && data[soul])\n })\n })\n }\n\n // Initialize rate limiting and connection management\n // Check if test environment (mock-socket usage)\n const isTestEnv = isNode && globalThis.WebSocket !== wsModule?.WebSocket\n const rateLimiter = createRateLimiter(isTestEnv)\n const connectionManager = createConnectionManager(opt.maxConnections || 1000)\n\n // User storage limiting \u2014 server-side only, requires opt.userLimit: true.\n const DEFAULT_STORAGE_LIMIT = 1 // 1 MB\n const defaultLimit =\n (typeof opt.defaultLimit === \"number\"\n ? opt.defaultLimit\n : DEFAULT_STORAGE_LIMIT) * 1048576\n const userStorage = new Map() // Map<pubkey, totalBytes>\n const userLimits = new Map() // Map<pubkey, maxBytes> converted from MB in .user_limit.json\n let saveStorageTimer = null\n\n const loadUserStorage = cb => {\n fs.readFile(`${opt.file}/../.user_storage.json`, \"utf8\", (err, raw) => {\n if (err) {\n if (cb) cb()\n return\n }\n\n try {\n const data = JSON.parse(raw)\n userStorage.clear()\n for (const [pub, total] of Object.entries(data)) {\n if (typeof total === \"number\") userStorage.set(pub, total)\n }\n } catch {\n // Invalid JSON \u2014 start with empty map.\n }\n if (cb) cb()\n })\n }\n\n const saveUserStorage = () => {\n if (saveStorageTimer) return\n\n const t = setTimeout(() => {\n saveStorageTimer = null\n const data = {}\n for (const [pub, total] of userStorage) {\n data[pub] = total\n }\n fs.writeFile(\n `${opt.file}/../.user_storage.json`,\n JSON.stringify(data),\n err => {\n if (err) console.warn(\"saveUserStorage error:\", err)\n },\n )\n }, 5000)\n if (t.unref) t.unref()\n saveStorageTimer = t\n }\n\n const loadUserLimits = cb => {\n fs.readFile(`${opt.file}/../.user_limit.json`, \"utf8\", (err, raw) => {\n if (err) {\n if (cb) cb()\n return\n }\n try {\n const data = JSON.parse(raw)\n userLimits.clear()\n for (const [pub, limit] of Object.entries(data)) {\n if (typeof limit === \"number\") userLimits.set(pub, limit * 1048576)\n // Non-numeric values ignored, falls back to defaultLimit.\n }\n } catch {\n // Invalid JSON \u2014 userLimits stays empty.\n }\n if (cb) cb()\n })\n }\n\n const formatBytes = bytes => {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(1)} MB`\n return `${(bytes / 1073741824).toFixed(1)} GB`\n }\n\n const logStorageSummary = () => {\n const userCount = userStorage.size\n const defLimitStr =\n defaultLimit === 0 ? \"unlisted users blocked\" : formatBytes(defaultLimit)\n console.log(\n `[HOLSTER] Per-user storage limits enabled (${userCount} user${userCount !== 1 ? \"s\" : \"\"}, default: ${defLimitStr})`,\n )\n const sorted = [...userStorage.entries()].sort(([, a], [, b]) => b - a)\n const logUser = pub => {\n const total = userStorage.get(pub) ?? 0\n const limit = userLimits.get(pub) ?? defaultLimit\n const limitStr = limit === 0 ? \"blocked\" : formatBytes(limit)\n console.log(\n ` ${pub.slice(0, 16)}... used: ${formatBytes(total)} / limit: ${limitStr}`,\n )\n }\n if (userCount <= 5) {\n sorted.forEach(([pub]) => logUser(pub))\n } else {\n console.log(\" Top 5 by storage used:\")\n sorted.slice(0, 5).forEach(([pub]) => logUser(pub))\n }\n console.log(\"Run npx holster-user-storage to view full keys and all users\")\n }\n\n // The check function is required because user data must provide a public key\n // so that it can be verified. The public key might verify the provided\n // signature but not actually match the user under which the data is being\n // stored. To avoid this, the current data on a soul needs to be checked to\n // make sure the stored public key matches the one provided with the update.\n // This must run before Ham.mix, which updates graph in place \u2014 checking\n // afterwards would compare the incoming update's public key against itself\n // instead of the previously stored one.\n const check = async (data, send, cb) => {\n const key = utils.userPublicKey\n\n for (const soul of Object.keys(data)) {\n const node = data[soul]\n // If the incoming update doesn't include a userPublicKey property at all,\n // allow it - the update is not trying to change the public key.\n if (node[key] === undefined) continue\n\n // A full-node lookup is required (rather than a targeted property\n // lookup) so that a soul which exists but has never had a public key\n // can be told apart from a soul that doesn't exist yet \u2014 both would\n // otherwise resolve to the same \"not found\" shape for this one key.\n const msg = await new Promise(res => {\n getWithCallback({\"#\": soul}, res, send, {put: true})\n })\n if (msg.err) {\n if (cb) cb(msg.err)\n return false\n }\n\n // If there is no current node then the data is ok to write without\n // matching public keys, as the provided soul also needs a rel on the\n // parent node which then also requires checking. Otherwise public keys\n // need to match for existing data.\n const existing = msg.put && msg.put[soul]\n if (\n !existing ||\n existing[key] === undefined ||\n existing[key] === node[key]\n ) {\n continue\n }\n\n // If a soul exists but does not have a public key, then one should not be\n // added because the node is not user data. The above check fails in this\n // case if a public key is provided. Note that this is only an error case\n // if called via the API, which is when a callback is provided here.\n // (The wire spec can fetch and put data on the wire without a signature\n // or public key and this can be ignored.)\n if (cb) {\n cb(`error in wire check public key does not match for soul: ${soul}`)\n }\n return false\n }\n\n return true\n }\n\n const get = (msg, send) => {\n const ack = Get(msg.get, graph)\n if (ack) {\n send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n put: ack,\n }),\n )\n } else {\n store.get(msg.get, (err, ack) => {\n send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n put: ack,\n err: err,\n }),\n )\n })\n }\n }\n\n const put = async (msg, send) => {\n // Capture old graph sizes before Ham.mix updates graph in place.\n const oldGraphBytes = {}\n if (opt.userLimit) {\n for (const [soul, node] of Object.entries(msg.put)) {\n if (node && node[utils.userPublicKey] && graph[soul]) {\n oldGraphBytes[soul] = JSON.stringify(graph[soul]).length\n }\n }\n }\n\n if (!(await check(msg.put, send))) return\n\n // Store updates returned from Ham.mix and defer updates if required.\n const update = await Ham.mix(\n msg.put,\n graph,\n hasNode,\n opt.secure,\n listen,\n opt.maxGraphSize,\n )\n if (Object.keys(update.now).length === 0) {\n // No updates to store, check deferred.\n if (Object.keys(update.defer).length !== 0) {\n setTimeout(\n () => put({put: update.defer, \"#\": msg[\"#\"]}, send),\n update.wait,\n )\n }\n return\n }\n\n const finish = err => {\n if (err) console.warn(\"store.put\", err)\n send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n err: err,\n }),\n )\n // Fire listeners after data is stored\n update.listeners.forEach(cb => cb())\n }\n\n if (!opt.userLimit) {\n store.put(update.now, finish)\n } else {\n const toStore = {}\n for (const [soul, node] of Object.entries(update.now)) {\n const pub = node[utils.userPublicKey]\n if (!pub) {\n toStore[soul] = node\n continue\n }\n const limit = userLimits.get(pub) ?? defaultLimit\n if ((userStorage.get(pub) ?? 0) >= limit) continue\n toStore[soul] = node\n const oldBytes = oldGraphBytes[soul] ?? 0\n const newBytes = graph[soul] ? JSON.stringify(graph[soul]).length : 0\n userStorage.set(\n pub,\n Math.max(0, (userStorage.get(pub) ?? 0) - oldBytes + newBytes),\n )\n saveUserStorage()\n }\n if (Object.keys(toStore).length > 0) {\n store.put(toStore, finish)\n } else {\n finish(null)\n }\n }\n\n if (Object.keys(update.defer).length !== 0) {\n setTimeout(\n () => put({put: update.defer, \"#\": msg[\"#\"]}, send),\n update.wait,\n )\n }\n }\n\n const getWithCallback = (lex, cb, send, _opt) => {\n if (!cb) return\n\n if (!utils.obj.is(_opt)) _opt = {}\n\n // For full-node requests on souls that have been fully fetched from store,\n // treat the graph as authoritative \u2014 skip the redundant store round-trip.\n const fast = _opt.fast || (!lex[\".\"] && hasNode.has(lex[\"#\"]))\n const ack = Get(lex, graph, fast)\n const track = utils.text.random(9)\n const request = JSON.stringify({\n \"#\": dup.track(track),\n get: lex,\n })\n\n if (ack) {\n if (!isNode) {\n // Client: send request on the wire to check for updates,\n // since it may have missed puts while disconnected.\n // Skip if the same lex was checked recently to avoid flooding.\n if (!lex[\".\"] || typeof lex[\".\"] === \"string\") {\n const checkKey = lex[\"#\"] + (lex[\".\"] ? \".\" + lex[\".\"] : \"\")\n const now = Date.now()\n const lastCheck = recentChecks.get(checkKey)\n if (!lastCheck || now - lastCheck > recentCheckTTL) {\n recentChecks.set(checkKey, now)\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n } else {\n // Don't skip checks for other types of lex queries.\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n }\n cb({put: ack})\n return\n }\n\n store.get(lex, (err, ack) => {\n if (ack) {\n // Populate in-memory graph from store data before sending the server\n // request, so stale server responses with older state are correctly\n // rejected by ham.mix.\n for (const [soul, node] of Object.entries(ack)) {\n if (!node) continue\n if (!graph[soul]) {\n graph[soul] = {...node}\n continue\n }\n // Merge properties absent from the current graph entry. Only add\n // missing keys \u2014 existing entries were set by ham.mix and represent\n // the authoritative merged state for those properties.\n for (const [key, value] of Object.entries(node)) {\n if (key === \"_\") continue\n if (typeof graph[soul][key] !== \"undefined\") continue\n graph[soul][key] = value\n if (\n node._ &&\n node._[\">\"] &&\n typeof node._[\">\"][key] !== \"undefined\"\n ) {\n const state = node._[\">\"][key]\n graph[soul]._[\">\"][key] = state\n if (node._[\"s\"] && node._[\"s\"][state]) {\n if (!graph[soul]._[\"s\"]) graph[soul]._[\"s\"] = {}\n graph[soul]._[\"s\"][state] = node._[\"s\"][state]\n }\n }\n }\n }\n // Full-node fetch: the graph is now complete for this soul.\n if (!lex[\".\"] && ack[lex[\"#\"]]) hasNode.add(lex[\"#\"])\n // Only serve from store if the requested property is present.\n const node = ack[lex[\"#\"]]\n const hasProperty =\n node &&\n Object.keys(node).some(\n key => key !== \"_\" && utils.match(lex[\".\"], key),\n )\n if (hasProperty) {\n // Public keys are immutable once written \u2014 never need a wire check.\n if (!isNode && lex[\".\"] !== utils.userPublicKey) {\n if (!lex[\".\"] || typeof lex[\".\"] === \"string\") {\n const checkKey = lex[\"#\"] + (lex[\".\"] ? \".\" + lex[\".\"] : \"\")\n const now = Date.now()\n const lastCheck = recentChecks.get(checkKey)\n if (!lastCheck || now - lastCheck > recentCheckTTL) {\n recentChecks.set(checkKey, now)\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n } else {\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n }\n cb(err ? {put: ack, err: err} : {put: ack})\n return\n }\n }\n\n // Data wasn't found locally, log errors and call back after a timeout.\n if (err) console.log(err)\n\n // Put requests only need a local answer \u2014 skip the wire round-trip.\n if (_opt && _opt.put) {\n const id = lex[\"#\"]\n const ack = {[id]: null}\n if (typeof lex[\".\"] === \"string\") {\n ack[id] = {[lex[\".\"]]: null}\n }\n cb({put: ack})\n return\n }\n\n queue[track] = cb\n\n // Store lex to construct the null ack when the timeout fires\n pendingTimeouts.set(track, lex)\n\n // Ensure the requested soul is stored when the response arrives.\n pendingReferences.add(lex[\"#\"])\n\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n delete queue[track]\n pendingTimeouts.delete(track)\n return\n }\n })\n }\n\n const api = send => {\n return {\n get: (lex, cb, _opt) => {\n if (lex && typeof lex[\".\"] === \"number\") {\n lex = {...lex, \".\": String(lex[\".\"])}\n }\n // Mark requested soul as something we want to store\n if (lex && lex[\"#\"]) {\n pendingReferences.add(lex[\"#\"])\n }\n getWithCallback(lex, cb, send, _opt)\n },\n put: async (data, cb) => {\n // Deferred updates are only stored using wire spec, they're ignored\n // here using the api. This is ok because correct timestamps should be\n // used whereas wire spec needs to handle clock skew for updates\n // across the network.\n const oldGraphBytes = {}\n if (opt.userLimit) {\n for (const [soul, node] of Object.entries(data)) {\n if (node && node[utils.userPublicKey] && graph[soul]) {\n oldGraphBytes[soul] = JSON.stringify(graph[soul]).length\n }\n }\n }\n if (!(await check(data, send, cb))) {\n return\n }\n\n const update = await Ham.mix(\n data,\n graph,\n hasNode,\n opt.secure,\n listen,\n opt.maxGraphSize,\n )\n if (Object.keys(update.now).length === 0) {\n // No updates, still respond to callback.\n if (cb) cb(null)\n return\n }\n\n // Ham.mix has already merged this locally-authored update into\n // graph[soul], synchronously, before store.put below even starts\n // persisting it - mark it as fully known now rather than waiting\n // for a future disk fetch to do so, so a read landing in that\n // window doesn't get forced through a disk round-trip that could\n // itself race ahead of this same write and find nothing, even\n // though the correct answer was already sitting in memory.\n for (const soul of Object.keys(update.now)) {\n hasNode.add(soul)\n }\n\n if (opt.userLimit) {\n for (const [soul, node] of Object.entries(update.now)) {\n const pub = node[utils.userPublicKey]\n if (!pub) continue\n const limit = userLimits.get(pub) ?? defaultLimit\n const current = userStorage.get(pub) ?? 0\n if (current >= limit) {\n if (cb) cb(\"storage limit exceeded\")\n return\n }\n\n const oldBytes = oldGraphBytes[soul] ?? 0\n const newBytes = graph[soul]\n ? JSON.stringify(graph[soul]).length\n : 0\n userStorage.set(pub, Math.max(0, current - oldBytes + newBytes))\n saveUserStorage()\n }\n }\n\n // Seed pendingReferences with any new references from API calls\n for (const [soul, node] of Object.entries(update.now)) {\n if (node && typeof node === \"object\") {\n for (const [key, value] of Object.entries(node)) {\n const soulId = utils.rel.is(value)\n if (soulId) {\n // Add referenced soul to pending list\n pendingReferences.add(soulId)\n }\n }\n }\n }\n\n store.put(update.now, err => {\n if (cb) cb(err)\n // Fire listeners after data is stored\n update.listeners.forEach(l => l())\n })\n\n // Always put data on the wire spec even if no local update needed\n const sendResult = send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n put: data,\n }),\n )\n // Handle queue overflow error.\n if (sendResult && sendResult.err) {\n if (cb) cb(sendResult.err)\n return\n }\n },\n on: (lex, cb, _get, _opt) => {\n if (lex && typeof lex[\".\"] === \"number\") {\n lex = {...lex, \".\": String(lex[\".\"])}\n }\n const soul = lex && lex[\"#\"]\n if (!soul || !cb) return\n\n if (listen[soul]) {\n listen[soul].push({\".\": lex[\".\"], cb: cb})\n } else {\n listen[soul] = [{\".\": lex[\".\"], cb: cb}]\n }\n if (_get) getWithCallback(lex, cb, send, _opt)\n },\n off: (lex, cb) => {\n const soul = lex && lex[\"#\"]\n if (!soul || !listen[soul]) return\n\n if (cb) {\n const found = listen[soul].find(l => l.cb === cb)\n if (found) {\n listen[soul].splice(listen[soul].indexOf(found), 1)\n }\n } else {\n // Remove all callbacks when none provided.\n delete listen[soul]\n }\n },\n }\n }\n\n if (isNode && (opt.wss || opt.server || opt.port != null)) {\n let wss = opt.wss\n // Node's websocket server provides clients as an array, whereas\n // mock-sockets provides clients as a function that returns an array.\n let clients = () => wss.clients()\n if (!wss) {\n const config = opt.server ? {server: opt.server} : {port: opt.port}\n wss = new wsModule.WebSocketServer(config)\n clients = () => wss.clients\n }\n\n const send = (data, isBinary) => {\n // Start timeout for this message now that it's being sent\n const msg = JSON.parse(data)\n const trackId = msg[\"#\"]\n if (trackId && pendingTimeouts.has(trackId)) {\n const lex = pendingTimeouts.get(trackId)\n pendingTimeouts.delete(trackId)\n\n setTimeout(\n () => {\n const cb = queue[trackId]\n if (cb) {\n const id = lex[\"#\"]\n const ack = {[id]: null}\n if (typeof lex[\".\"] === \"string\") {\n ack[id] = {[lex[\".\"]]: null}\n }\n cb({put: ack})\n delete queue[trackId]\n }\n },\n isTestEnv ? 100 : 10000,\n )\n }\n\n clients().forEach(client => {\n if (client && client.readyState === WebSocket.OPEN) {\n client.send(data, {binary: isBinary})\n } else {\n const retryHandler = client._retryHandler || createRetryHandler()\n client._retryHandler = retryHandler\n\n if (retryHandler.shouldRetry()) {\n const delay = retryHandler.getDelay()\n retryHandler.increment()\n\n setTimeout(() => {\n if (client && client.readyState === WebSocket.OPEN) {\n retryHandler.reset()\n client.send(data, {binary: isBinary})\n }\n }, delay)\n }\n }\n })\n }\n if (opt.userLimit) {\n loadUserStorage(() => loadUserLimits(() => logStorageSummary()))\n setInterval(loadUserLimits, 60000).unref()\n }\n\n wss.on(\"connection\", ws => {\n // Check connection limit\n if (!connectionManager.add(ws)) {\n console.log(\"Connection limit reached, rejecting connection\")\n ws.close(1013, \"Connection limit reached - try again later\")\n return\n }\n\n // Generate unique client ID for rate limiting\n const clientId = utils.text.random(9)\n console.log(`New WebSocket client connected: ${clientId}`)\n\n ws.on(\"error\", error => {\n console.log(\"WebSocket error:\", error)\n connectionManager.remove(ws)\n })\n\n ws.on(\"close\", () => {\n console.log(`WebSocket client disconnected: ${clientId}`)\n connectionManager.remove(ws)\n })\n\n ws.on(\"message\", (data, isBinary) => {\n // Validate message size\n const validation = validateMessage(data, opt.maxMessageSize)\n if (!validation.valid) {\n console.warn(`Invalid message: ${validation.error}`)\n ws.send(JSON.stringify({error: validation.error}))\n return\n }\n\n // Safe JSON parsing\n const parseResult = safeJSONParse(data, opt.maxMessageSize)\n if (!parseResult.success) {\n console.warn(`JSON parse error: ${parseResult.error}`)\n ws.send(JSON.stringify({error: \"Invalid JSON\"}))\n return\n }\n\n const msg = parseResult.data\n if (dup.check(msg[\"#\"])) return\n\n // Check rate limit and get delay\n const delay = rateLimiter.getDelay(clientId)\n // Log rate limiting activity and enforce stricter limits\n if (delay > 0) {\n const throttleCount = rateLimiter.getThrottleCount(clientId)\n console.log(\n `Client ${clientId}: rate limit exceeded, delay would be ${delay}ms, dropping message (throttle count: ${throttleCount})`,\n )\n // Check if we should disconnect the bad actor\n if (rateLimiter.shouldDisconnect(clientId)) {\n console.log(\n `Client ${clientId}: Disconnecting after ${throttleCount} throttle violations`,\n )\n ws.close(1008, \"Rate limit violations\")\n return\n }\n\n // Send throttle warning back to client instead of processing\n ws.send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n err: `Rate limit exceeded. Slow down requests. Wait ${Math.ceil(delay / 1000)}s`,\n throttle: delay,\n }),\n )\n return\n }\n\n const processMessage = async () => {\n dup.track(msg[\"#\"])\n\n if (msg.get) get(msg, send)\n if (msg.put) await put(msg, send)\n send(data, isBinary)\n\n const id = msg[\"@\"]\n const cb = queue[id]\n if (cb) {\n delete msg[\"#\"]\n delete msg[\"@\"]\n cb(msg)\n\n delete queue[id]\n }\n }\n\n if (delay > 0) {\n // Throttle the client by delaying message processing\n setTimeout(processMessage, delay)\n } else {\n // Process immediately\n processMessage()\n }\n })\n })\n return api(send)\n }\n\n // Browser logic.\n const peers = []\n // Client-side throttling state\n let clientThrottled = false\n let throttleUntil = 0\n let messageQueue = []\n let offlinePuts = []\n let queueProcessor = null\n const maxQueueLength = opt.maxQueueLength || 10000\n\n const startResponseTimeout = (\n trackId,\n lex,\n delay = isTestEnv ? 100 : 10000,\n ) => {\n return setTimeout(() => {\n offlineTimeouts.delete(trackId)\n pendingTimeouts.delete(trackId)\n const cb = queue[trackId]\n // No-op on successful send as callback is removed from the queue.\n if (cb) {\n const id = lex[\"#\"]\n const ack = {[id]: null}\n if (typeof lex[\".\"] === \"string\") {\n ack[id] = {[lex[\".\"]]: null}\n }\n cb({put: ack})\n delete queue[trackId]\n }\n }, delay)\n }\n\n const processQueue = () => {\n if (messageQueue.length === 0) {\n queueProcessor = null\n return\n }\n\n const now = Date.now()\n if (clientThrottled && now < throttleUntil) {\n // Still throttled, schedule next queue check\n queueProcessor = setTimeout(\n processQueue,\n Math.min(1000, throttleUntil - now),\n )\n return\n }\n\n // Throttle period ended, resume processing\n if (clientThrottled && now >= throttleUntil) {\n console.log(`Throttle period ended, resuming queue processing`)\n clientThrottled = false\n throttleUntil = 0\n }\n\n // Process next message in queue\n const data = messageQueue[0]\n const sent = sendToPeers(data)\n\n const msg = JSON.parse(data)\n const trackId = msg[\"#\"]\n\n // Drop GET messages with no pending callback \u2014 these were already served\n // from local store so no caller is waiting for the wire response.\n const isStaleCheckMessage =\n !sent && msg.get && !pendingTimeouts.has(trackId)\n\n if (sent || isStaleCheckMessage) {\n messageQueue.shift()\n } else if (!sent && msg.put) {\n // Hold offline PUTs separately so they don't block GET messages behind\n // them. They'll be flushed back to the front of the queue on reconnect.\n messageQueue.shift()\n offlinePuts.push(data)\n }\n\n if (trackId && pendingTimeouts.has(trackId)) {\n const lex = pendingTimeouts.get(trackId)\n if (sent) {\n if (offlineTimeouts.has(trackId)) {\n clearTimeout(offlineTimeouts.get(trackId))\n offlineTimeouts.delete(trackId)\n }\n startResponseTimeout(trackId, lex)\n } else if (!offlineTimeouts.has(trackId)) {\n offlineTimeouts.set(trackId, startResponseTimeout(trackId, lex, 0))\n }\n }\n\n // Schedule processing of next message if queue not empty\n if (messageQueue.length > 0) {\n // Add delay between messages to respect rate limit\n queueProcessor = setTimeout(processQueue, 50)\n } else {\n queueProcessor = null\n }\n }\n\n const sendToPeers = data => {\n let sentToAtLeastOne = false\n peers.forEach(peer => {\n if (peer && peer.readyState === WebSocket.OPEN) {\n peer.send(data)\n sentToAtLeastOne = true\n } else {\n const retryHandler = peer._retryHandler || createRetryHandler()\n peer._retryHandler = retryHandler\n\n if (retryHandler.shouldRetry()) {\n const delay = retryHandler.getDelay()\n retryHandler.increment()\n\n setTimeout(() => {\n if (peer && peer.readyState === WebSocket.OPEN) {\n retryHandler.reset()\n peer.send(data)\n }\n }, delay)\n }\n }\n })\n return sentToAtLeastOne\n }\n\n const send = data => {\n if (messageQueue.length >= maxQueueLength) {\n return {\n err: `Message queue exceeded maximum length (${maxQueueLength}). Update query logic to request less data.`,\n queueLength: messageQueue.length,\n maxQueueLength: maxQueueLength,\n }\n }\n\n messageQueue.push(data)\n // Start queue processor if not already running\n if (!queueProcessor) {\n queueProcessor = setTimeout(processQueue, 50)\n }\n }\n if (!(opt.peers instanceof Array) || opt.peers.length === 0) {\n opt.peers = [`ws://localhost:${opt.port || 8765}`]\n }\n opt.peers.forEach(peer => {\n const start = () => {\n let ws = new WebSocket(peer)\n peers.push(ws)\n const retryHandler = createRetryHandler()\n\n ws.onclose = c => {\n if (peers.indexOf(ws) !== -1) {\n peers.splice(peers.indexOf(ws), 1)\n }\n ws = null\n\n if (retryHandler.shouldRetry()) {\n const delay = isTestEnv ? 50 : retryHandler.getDelay()\n retryHandler.increment()\n const t = setTimeout(start, delay)\n if (t.unref) t.unref()\n }\n }\n\n ws.onopen = () => {\n retryHandler.reset()\n if (offlinePuts.length > 0) {\n messageQueue = offlinePuts.concat(messageQueue)\n offlinePuts = []\n if (!queueProcessor) {\n queueProcessor = setTimeout(processQueue, 50)\n }\n }\n }\n\n ws.onerror = e => {\n console.log(e)\n }\n ws.onmessage = async m => {\n const msg = JSON.parse(m.data)\n if (dup.check(msg[\"#\"])) return\n\n // Handle throttle messages from server\n if (msg.throttle && msg.err) {\n console.log(`Server throttling: ${msg.err}`)\n clientThrottled = true\n throttleUntil = Date.now() + msg.throttle\n return\n }\n\n dup.track(msg[\"#\"])\n if (msg.get) get(msg, send)\n if (msg.put) {\n // Pre-pass: expand pendingReferences to include rels of every soul\n // that will be stored in this batch. This handles the case where a\n // server batch contains both a parent soul (e.g. day_soul with item\n // rels) and its child souls (item_souls), in any order \u2014 without the\n // pre-pass, a child soul that appears before its parent in the batch\n // would be missed because pendingReferences hasn't been updated yet.\n const hasSoulMap = new Map()\n for (const [soul, node] of Object.entries(msg.put)) {\n const known = await hasSoul(soul)\n hasSoulMap.set(soul, known)\n if (\n (!known && !pendingReferences.has(soul)) ||\n !node ||\n typeof node !== \"object\"\n )\n continue\n for (const [, value] of Object.entries(node)) {\n const soulId = utils.rel.is(value)\n if (soulId) pendingReferences.add(soulId)\n }\n }\n\n // Main pass: filter using cached hasSoul results and the now-complete\n // pendingReferences set.\n const filteredPut = {}\n const pendingToDelete = []\n for (const [soul, node] of Object.entries(msg.put)) {\n let shouldStore = hasSoulMap.get(soul)\n if (pendingReferences.has(soul)) {\n shouldStore = true\n // Don't delete from pendingReferences yet \u2014 concurrent onmessage\n // handlers for the same soul may have yielded at await hasSoul()\n // before this pass ran. Deleting here would cause those handlers\n // to see shouldStore=false and skip storing the soul's data.\n // Instead, defer the delete until after put() updates the graph,\n // so any concurrent handler can find the soul via hasSoul(graph).\n pendingToDelete.push(soul)\n }\n if (shouldStore) filteredPut[soul] = node\n }\n\n // Store filtered data if any\n if (Object.keys(filteredPut).length > 0) {\n // Create filtered message for Ham.mix with original message ID\n const filteredMsg = {put: filteredPut, \"#\": msg[\"#\"]}\n await put(filteredMsg, send)\n }\n\n // Safe to delete now \u2014 put() has run Ham.mix which updates graph\n // in-place, so hasSoul() will return true for these souls going\n // forward, making pendingReferences no longer needed for them.\n pendingToDelete.forEach(soul => pendingReferences.delete(soul))\n }\n\n const id = msg[\"@\"]\n const cb = queue[id]\n if (cb) {\n delete msg[\"#\"]\n delete msg[\"@\"]\n cb(msg)\n\n delete queue[id]\n }\n }\n }\n start()\n })\n\n return api(send)\n}\n\nexport default Wire\n", "import * as utils from \"./utils.js\"\nimport Wire from \"./wire.js\"\nimport SEA from \"./sea.js\"\nimport {userPublicKey, userSignature} from \"./utils.js\"\n\nconst User = (opt, wire) => {\n if (!wire) wire = Wire(opt)\n let pubs = []\n let creating = false\n let authing = false\n let retries = 0\n\n const auth = (username, password, newPassword, ack) => {\n const retry = username => {\n retries++\n auth(username, password, newPassword, ack)\n }\n const done = err => {\n pubs = []\n retries = 0\n authing = false\n ack(err)\n }\n const next = () => {\n if (pubs.length === 0) {\n done(\"Wrong username or password\")\n return\n }\n\n const pub = pubs.shift()\n wire.get({\"#\": pub, \".\": [\"auth\", \"pub\", \"epub\"]}, async msg => {\n if (msg.err) {\n done(`error getting ${pub}: ${msg.err}`)\n return\n }\n\n const data = msg.put && msg.put[pub]\n if (!data || !data.auth) return next()\n\n const auth = JSON.parse(data.auth)\n const work = await SEA.work(password, auth.salt)\n const dec = await SEA.decrypt(auth.enc, work)\n if (!dec) return next()\n\n user.is = {\n username: username,\n pub: data.pub,\n epub: data.epub,\n priv: dec.priv,\n epriv: dec.epriv,\n }\n if (newPassword !== \"\") {\n // Encrypt private key using new password and a new salt.\n const salt = utils.text.random(64)\n const work = await SEA.work(newPassword, salt)\n const enc = await SEA.encrypt(dec, work)\n // Only update the auth property with the new password encryption.\n const update = {\n auth: JSON.stringify({enc: enc, salt: salt}),\n }\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, user.is)\n const graph = utils.graph(pub, update, sig, data.pub, timestamp)\n wire.put(graph, err => {\n if (err) {\n done(`error putting ${update} on ${pub}: ${err}`)\n } else {\n done(null)\n }\n })\n return\n }\n\n done(null)\n })\n }\n\n if (retries > 9) {\n done(\"Wrong username or password\")\n return\n }\n\n const soul = \"~@\" + username\n wire.get({\"#\": soul}, async msg => {\n if (msg.err) {\n done(`error getting ${soul}: ${msg.err}`)\n return\n }\n\n const data = msg.put && msg.put[soul]\n if (!data) return retry(username)\n\n delete msg.put[soul]._\n // Usernames aren't guaranteed to be unique, so store the list and then\n // try each of them until one is successful with the given password.\n pubs = Object.keys(data)\n next()\n })\n }\n\n const user = {\n create: (username, password, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else console.log(err)\n }\n\n if (creating) {\n ack(\"User is already being created\")\n return\n }\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n creating = true\n\n const soul = \"~@\" + username\n wire.get({\"#\": soul}, async msg => {\n if (msg.err) {\n creating = false\n ack(`error getting ${soul}: ${msg.err}`)\n return\n }\n\n if (msg.put && msg.put[soul]) {\n creating = false\n ack(\"Username already exists\")\n return\n }\n\n const salt = utils.text.random(64)\n const work = await SEA.work(password, salt)\n const pair = await SEA.pair()\n const priv = {priv: pair.priv, epriv: pair.epriv}\n const enc = await SEA.encrypt(priv, work)\n const data = {\n username: username,\n pub: pair.pub,\n epub: pair.epub,\n auth: JSON.stringify({enc: enc, salt: salt}),\n }\n\n const pub = \"~\" + pair.pub\n // Sign the timestamp for new account\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, pair)\n const graph = utils.graph(pub, data, sig, pair.pub, timestamp)\n wire.put(graph, err => {\n creating = false\n if (err) {\n ack(`error putting ${data} on ${pub}: ${err}`)\n return\n }\n\n const rel = {[pub]: {\"#\": pub}}\n wire.put(utils.graph(soul, rel), err => {\n if (err) {\n ack(`error putting ${rel} on ${soul}: ${err}`)\n return\n }\n\n // Return null on success.\n if (cb) cb(null)\n })\n })\n })\n },\n auth: (username, password, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else if (err) console.log(err)\n }\n\n if (authing) {\n ack(\"User is already authenticating\")\n return\n }\n\n user.is = null\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n authing = true\n auth(username, password, \"\", ack)\n },\n change: (username, password, newPassword, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else if (err) console.log(err)\n }\n\n if (authing) {\n ack(\"User is already authenticating\")\n return\n }\n\n user.is = null\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n if (newPassword === \"\") {\n ack(\"Please provide a new password\")\n return\n }\n\n authing = true\n auth(username, password, newPassword, ack)\n },\n store: localStorage => {\n if (!user.is) {\n console.log(\"Please authenticate before calling store\")\n return\n }\n\n if (localStorage) {\n if (typeof globalThis.localStorage !== \"undefined\") {\n globalThis.localStorage.setItem(\"user.is\", JSON.stringify(user.is))\n }\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n globalThis.sessionStorage.removeItem(\"user.is\")\n }\n return\n }\n\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n globalThis.sessionStorage.setItem(\"user.is\", JSON.stringify(user.is))\n }\n if (typeof globalThis.localStorage !== \"undefined\") {\n globalThis.localStorage.removeItem(\"user.is\")\n }\n },\n recall: () => {\n if (typeof globalThis.localStorage !== \"undefined\") {\n const is = globalThis.localStorage.getItem(\"user.is\")\n if (is) {\n user.is = JSON.parse(is)\n return\n }\n }\n\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n const is = globalThis.sessionStorage.getItem(\"user.is\")\n if (is) {\n user.is = JSON.parse(is)\n }\n }\n },\n leave: () => {\n user.is = null\n if (typeof globalThis.localStorage !== \"undefined\") {\n globalThis.localStorage.removeItem(\"user.is\")\n }\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n globalThis.sessionStorage.removeItem(\"user.is\")\n }\n },\n delete: (username, password, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else console.log(err)\n }\n\n if (authing) {\n ack(\"User is already authenticating\")\n return\n }\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n authing = true\n auth(username, password, \"\", async err => {\n if (err) {\n ack(err)\n return\n }\n\n const data = {username: null, pub: null, epub: null, auth: null}\n // Sign the timestamp for account deletion\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, user.is)\n const pub = \"~\" + user.is.pub\n const graph = utils.graph(pub, data, sig, user.is.pub, timestamp)\n wire.put(graph, err => {\n if (err) {\n ack(`error putting null on ${pub}: ${err}`)\n return\n }\n\n user.is = null\n // Return null on success. Note currently not updating ~@username,\n // not sure if allowing username re-user is a good idea anyway?\n if (cb) cb(null)\n })\n })\n },\n }\n return user\n}\n\nexport default User\n", "import * as utils from \"./utils.js\"\nimport Wire from \"./wire.js\"\nimport User from \"./user.js\"\nimport SEA from \"./sea.js\"\n\nconst Holster = opt => {\n if (typeof opt === \"string\") opt = {peers: [opt]}\n else if (opt instanceof Array) opt = {peers: opt}\n else if (!utils.obj.is(opt)) opt = {}\n\n const wire = Wire(opt)\n const user = User(opt, wire)\n // Map callbacks since the user's callback is not passed to wire.on.\n const map = new Map()\n // Allow concurrent calls to the api by storing each context.\n const allctx = new Map()\n // Serializes concurrent creation of a missing rel for the same\n // soul+item, so only the first caller creates it and the rest reuse\n // its result rather than each minting a competing soul. Map<soul,\n // Map<item, promise resolving to the soul id>>.\n const pendingRel = new Map()\n\n const ok = data => {\n return (\n data === null ||\n data === true ||\n data === false ||\n typeof data === \"string\" ||\n utils.rel.is(data) ||\n utils.num.is(data)\n )\n }\n\n // check returns true if data is ok to add to a graph, an error string if\n // the data can't be converted, and the keys on the data object otherwise.\n const check = data => {\n if (ok(data)) return true\n\n if (utils.obj.is(data)) {\n const keys = []\n for (const [key, value] of Object.entries(data)) {\n if (key === \"_\") {\n return \"error underscore cannot be used as a property name\"\n }\n if (utils.obj.is(value) || ok(value)) {\n keys.push(key)\n continue\n }\n if (typeof value === \"undefined\") {\n return `error undefined ${key} cannot be converted to a graph`\n }\n const error = JSON.stringify({[key]: value})\n return `error ${error} cannot be converted to a graph`\n }\n if (keys.length !== 0) return keys\n }\n const error = JSON.stringify(data)\n return `error ${error} cannot be converted to a graph`\n }\n\n const api = ctxid => {\n const get = (lex, soul, ack, _opt) => {\n wire.get(\n utils.obj.put(lex, \"#\", soul),\n async msg => {\n if (msg.err) console.log(msg.err)\n if (msg.put && msg.put[soul]) {\n delete msg.put[soul]._\n delete msg.put[soul][utils.userPublicKey]\n delete msg.put[soul][utils.userSignature]\n // Resolve any rels on the node before returning to the user.\n await Promise.all(\n Object.keys(msg.put[soul]).map(async key => {\n const id = utils.rel.is(msg.put[soul][key])\n if (!id) return\n const attemptRead = async (retries = 0) => {\n const data = await new Promise(res => {\n const _ctxid = utils.text.random()\n const ctx = allctx.get(ctxid)\n allctx.set(_ctxid, {\n chain: [{item: null, soul: id}],\n user: ctx ? ctx.user : null,\n })\n api(_ctxid).next(null, res, _opt)\n })\n if (data !== null || retries >= 5) {\n return data\n }\n // Data not ready, retry after delay\n await new Promise(resolve => setTimeout(resolve, 50))\n return attemptRead(retries + 1)\n }\n msg.put[soul][key] = await attemptRead()\n }),\n )\n ack(msg.put[soul])\n } else {\n // No data callback.\n ack(null)\n }\n },\n _opt,\n )\n }\n\n const graph = async (soul, data, userctx, cb) => {\n if (userctx) {\n // Sign the timestamp\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, userctx)\n return utils.graph(soul, data, sig, userctx.pub, timestamp)\n }\n\n if (opt.secure) {\n if (!cb) cb = console.log\n cb(`error putting data on ${soul}: user required in secure mode`)\n return null\n }\n\n return utils.graph(soul, data)\n }\n\n // done takes a context id and returns a new callback function so that the\n // callback is not overwritten by simultaneous requests.\n const done = ctxid => {\n return data => {\n const ctx = allctx.get(ctxid)\n if (ctx && typeof ctx.cb !== \"undefined\") {\n // Use a timeout so that the context can be removed before data is\n // returned to the callback (allows nested get calls).\n setTimeout(() => ctx.cb(data), 1)\n } else if (data) {\n console.log(\"error no callback for data\", data, \"ctx\", ctx)\n }\n // A context updated by \"on\" should only be removed by \"off\".\n if (ctx && !ctx.on) allctx.delete(ctxid)\n }\n }\n\n const watchForRel = (soul, item, ctx, i, request, cb, on = true) => {\n let timer = null\n const handler = () => {\n // Bail out if the context was removed by off().\n if (!allctx.has(ctxid)) {\n wire.off({\"#\": soul, \".\": item}, handler)\n if (timer) clearTimeout(timer)\n return\n }\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n const node = msg.put && msg.put[soul]\n const id = utils.rel.is(node && node[item])\n if (!id) {\n // If it's a plain value (not a rel) and this is a get, deliver it.\n // node._ guards against timeout null-acks which lack metadata.\n if (!on && node && node._ && typeof node[item] !== \"undefined\") {\n if (timer) clearTimeout(timer)\n wire.off({\"#\": soul, \".\": item}, handler)\n cb(node[item])\n }\n return\n }\n if (timer) clearTimeout(timer)\n wire.off({\"#\": soul, \".\": item}, handler)\n ctx.chain[i].soul = id\n allctx.set(ctxid, {...ctx})\n if (on) {\n api(ctxid).on(request.on, cb, request._get, request._opt)\n } else {\n api(ctxid).next(null, request.get, cb, request._opt)\n }\n },\n {...request._opt, secure: !!(ctx.user || opt.secure)},\n )\n }\n wire.on({\"#\": soul, \".\": item}, handler, false, request._opt)\n // Time out after the same total duration as the on() retry loop\n // (1+2+4+8+16 = 31s) so callers are not blocked forever if the node\n // genuinely doesn't exist.\n if (!on) {\n timer = setTimeout(() => {\n wire.off({\"#\": soul, \".\": item}, handler)\n if (cb) cb(null)\n }, 31000)\n }\n }\n\n // Creates a rel for item on soul, or reuses one already being created\n // by a concurrent caller for the same soul+item (see pendingRel above).\n // Calls cb(err, id) with a ready-to-display err, already prefixed where\n // needed - callers should pass it straight through, not wrap it again.\n const createRel = (soul, item, node, user, cb) => {\n let bySoul = pendingRel.get(soul)\n const pending = bySoul && bySoul.get(item)\n if (pending) {\n pending.then(\n id => cb(null, id),\n err => cb(err),\n )\n return\n }\n\n const id = utils.text.random()\n node[item] = utils.rel.ify(id)\n let settle, fail\n const promise = new Promise((res, rej) => {\n settle = res\n fail = rej\n })\n promise.catch(() => {})\n if (!bySoul) {\n bySoul = new Map()\n pendingRel.set(soul, bySoul)\n }\n bySoul.set(item, promise)\n const clear = () => {\n bySoul.delete(item)\n if (bySoul.size === 0) pendingRel.delete(soul)\n }\n\n ;(async () => {\n // graph() itself calls cb with an already-formatted message when it\n // fails (secure mode, no user) - pass cb straight through rather\n // than wrapping, so that message isn't prefixed a second time.\n const g = await graph(soul, node, user, cb)\n if (g === null) {\n clear()\n fail(new Error(\"secure mode\"))\n return\n }\n\n wire.put(g, err => {\n clear()\n if (err) {\n const message = `error putting ${item} on ${soul}: ${err}`\n fail(message)\n cb(message)\n return\n }\n\n settle(id)\n cb(null, id)\n })\n })()\n }\n\n const resolve = (request, cb) => {\n if (!request) {\n console.log(\"error resolve request parameter required\")\n return\n }\n\n const get = typeof request.get !== \"undefined\"\n const put = typeof request.put !== \"undefined\"\n const on = typeof request.on !== \"undefined\"\n const off = typeof request.off !== \"undefined\"\n\n let found = false\n const ctx = allctx.get(ctxid)\n if (!ctx) return {item: null, soul: null}\n for (var i = 1; i < ctx.chain.length; i++) {\n if (ctx.chain[i].soul !== null) continue\n\n found = true\n break\n }\n\n if (found) {\n // Found a soul that needs resolving, need the previous context\n // (ie the parent node) to find a soul relation for it.\n const {item, soul} = ctx.chain[i - 1]\n wire.get(\n {\"#\": soul, \".\": item},\n async msg => {\n if (msg.err) {\n console.log(`error getting ${item} on ${soul}: ${msg.err}`)\n if (cb) cb(null)\n return\n }\n\n let node = msg.put && msg.put[soul]\n if (node && typeof node[item] !== \"undefined\") {\n let id = utils.rel.is(node[item])\n if (id) {\n ctx.chain[i].soul = id\n allctx.set(ctxid, {...ctx})\n // Call api again using the updated context.\n if (get) {\n api(ctxid).next(null, request.get, cb, request._opt)\n } else if (put) {\n api(ctxid).put(request.put, cb)\n } else if (on) {\n api(ctxid).on(request.on, cb, request._get, request._opt)\n } else if (off) {\n api(ctxid).off(cb)\n }\n } else if (get) {\n // Request was not for a node, return property on current soul.\n cb(node[item])\n } else if (put) {\n // Request was chained before put, so rel doesn't exist yet.\n createRel(soul, item, node, ctx.user, (err, relId) => {\n if (err) {\n cb(err)\n return\n }\n\n ctx.chain[i].soul = relId\n api(ctxid).put(request.put, cb)\n })\n } else if (on) {\n // Item is not a rel yet \u2014 watch the parent soul for when it\n // becomes one, then retry chain resolution.\n watchForRel(soul, item, ctx, i, request, cb)\n if (request._get) cb(null)\n } else if (off) {\n // Allow stop listening to a node that doesn't exist.\n if (cb) cb(null)\n }\n } else if (put) {\n // Request was chained before put, so rel doesn't exist yet.\n createRel(soul, item, node || {}, ctx.user, (err, relId) => {\n if (err) {\n cb(err)\n return\n }\n\n ctx.chain[i].soul = relId\n api(ctxid).put(request.put, cb)\n })\n } else {\n if (on) {\n // Node doesn't exist yet \u2014 watch for it to appear.\n watchForRel(soul, item, ctx, i, request, cb)\n if (request._get) cb(null)\n } else if (get && node) {\n const sv = node._ && node._[\">\"]\n if (\n sv &&\n Object.keys(sv).length > 0 &&\n typeof sv[item] === \"undefined\"\n ) {\n // State vector has other properties but not this one \u2014 never written.\n if (cb) cb(null)\n } else {\n // Empty state vector or item is tracked \u2014 may arrive via push.\n watchForRel(soul, item, ctx, i, request, cb, false)\n }\n } else {\n // Soul doesn't exist or no get \u2014 return null.\n if (cb) cb(null)\n }\n }\n },\n {...request._opt, secure: !!(ctx.user || opt.secure)},\n )\n // Callback has been passed to next soul lookup or called above, so\n // return false as the calling code should not continue.\n return false\n }\n\n if (get && ctx.chain[ctx.chain.length - 1].item !== null) {\n // The context has been resolved but it does not include the requested\n // node, which requires one more lookup.\n ctx.chain.push({item: null, soul: null})\n api(ctxid).next(null, request.get, cb, request._opt)\n return false\n }\n\n // Return the last context, ie the soul required by the calling code.\n return ctx.chain[ctx.chain.length - 1]\n }\n\n return {\n get: (key, lex, cb, _opt) => {\n if (typeof lex === \"function\") {\n _opt = cb\n cb = lex\n lex = null\n }\n if (key === null || key === \"\" || key === \"_\") {\n console.log(\"error please provide a key\")\n if (cb) cb(null)\n return\n }\n\n // lex requires a callback as it's not included in the chain below.\n if (lex && typeof cb !== \"function\") {\n console.log(\"error lex requires a callback function\")\n return\n }\n\n // Top level keys are added to a root node so their values don't need\n // to be objects.\n ctxid = utils.text.random()\n allctx.set(ctxid, {chain: [{item: String(key), soul: \"root\"}], cb: cb})\n if (!cb) return api(ctxid)\n\n const _done = done(ctxid)\n // When there's a callback need to resolve the context first.\n const {soul} = resolve({get: lex, _opt: _opt}, _done)\n if (soul) get(lex, soul, _done, _opt)\n },\n next: (key, lex, cb, _opt) => {\n // ack needs to work the same as done, pass it the context id and then\n // return a new function for the actual callback.\n const ack = ctxid => {\n return data => {\n if (cb) {\n cb(data)\n } else {\n done(ctxid)(data)\n }\n }\n }\n if (typeof lex === \"function\") {\n _opt = cb\n cb = lex\n lex = null\n }\n if (!ctxid) {\n console.log(\"error please provide a key using get(key)\")\n if (cb) cb(null)\n return\n }\n\n const _ack = ack(ctxid)\n if (key === \"\" || key === \"_\") {\n _ack(null)\n return\n }\n\n // lex requires a callback as it's not included in the chain below.\n if (lex && typeof cb !== \"function\") {\n console.log(\"error lex requires a callback function\")\n return\n }\n\n const ctx = allctx.get(ctxid)\n // ctx already removed by another chained callback is ok?\n if (!ctx) return\n\n if (cb && typeof ctx.cb === \"undefined\") {\n // This (and ack) allows nested objects to set their own callbacks.\n ctx.cb = cb\n cb = null\n }\n\n // Push the key to the context as it needs a soul lookup.\n // (null is used to call the api with updated context)\n if (key !== null) ctx.chain.push({item: String(key), soul: null})\n if (!ctx.cb) return api(ctxid)\n\n // When there's a callback need to resolve the context first.\n const {soul} = resolve({get: lex, _opt: _opt}, _ack)\n if (soul) get(lex, soul, _ack, _opt)\n },\n put: (data, set, cb) => {\n if (typeof set === \"function\") {\n cb = set\n set = false\n }\n const ack = ctxid => {\n return data => {\n if (cb) {\n cb(data)\n } else {\n done(ctxid)(data)\n }\n }\n }\n if (!ctxid) {\n if (cb) cb(\"error please provide a key using get(key)\")\n return\n }\n\n const ctx = allctx.get(ctxid)\n // ctx already removed by another chained callback is ok?\n if (!ctx) return\n\n if (!ctx.cb && cb) {\n // This (and ack) allows nested objects to set their own callbacks.\n ctx.cb = cb\n cb = null\n }\n if (set) data = {[utils.text.random()]: data}\n\n const _ack = ack(ctxid)\n const result = check(data)\n if (typeof result === \"string\") {\n // All strings returned from check are errors, cannot continue.\n _ack(result)\n return\n }\n\n // Resolve the current context before putting data. (Note that set is\n // not passed to resolve because it's already been applied above.)\n const {item, soul} = resolve({put: data, _opt: {put: true}}, _ack)\n if (!soul) return\n\n if (result === true) {\n // When result is true data is a property to put on the current soul.\n // Need to check if item is a rel and also set the node to null. (This\n // applies for any update from a rel to a property, not just null.)\n wire.get(\n {\"#\": soul, \".\": item},\n async msg => {\n if (msg.err) {\n _ack(`error getting ${soul}: ${msg.err}`)\n return\n }\n\n let node = msg.put && msg.put[soul]\n const current = node && node[item]\n const id = utils.rel.is(current)\n if (!id) {\n // Not a rel, can just put the data.\n if (!node) node = {}\n node[item] = data\n const g = await graph(soul, node, ctx.user, _ack)\n if (g === null) return\n\n wire.put(g, _ack)\n return\n }\n\n wire.get({\"#\": id}, async msg => {\n if (msg.err) {\n _ack(`error getting ${id}: ${msg.err}`)\n return\n }\n\n if (!msg.put || !msg.put[id]) {\n _ack(`error ${id} not found`)\n return\n }\n\n // null each of the properties on the node before putting data.\n for (const key of Object.keys(msg.put[id])) {\n if (\n key === \"_\" ||\n key === utils.userPublicKey ||\n key === utils.userSignature\n ) {\n continue\n }\n\n const err = await new Promise(res => {\n const _ctxid = utils.text.random()\n const chain = [{item: key, soul: id}]\n allctx.set(_ctxid, {chain: chain, user: ctx.user})\n api(_ctxid).put(null, res)\n })\n if (err) {\n _ack(err)\n return\n }\n }\n if (!node) node = {}\n node[item] = data\n const g = await graph(soul, node, ctx.user, _ack)\n if (g === null) return\n\n wire.put(g, _ack)\n })\n },\n {secure: !!(ctx.user || opt.secure), put: true},\n )\n return\n }\n\n // Otherwise put the data using the keys returned in result.\n // Need to check if a rel has already been added on the current node.\n // Use attemptRead to retry if data hasn't propagated yet.\n const attemptRead = (retries = 0) => {\n wire.get(\n {\"#\": soul, \".\": item},\n async msg => {\n if (msg.err) {\n _ack(`error getting ${soul}.${item}: ${msg.err}`)\n return\n }\n\n let node = msg.put && msg.put[soul]\n const current = node && node[item]\n\n // If we didn't find the item but still have retries, retry\n if (!current && retries < 5) {\n await new Promise(r => setTimeout(r, 50))\n return attemptRead(retries + 1)\n }\n\n const id = utils.rel.is(current)\n if (!id) {\n // The current rel doesn't exist, so add it first.\n createRel(soul, item, node || {}, ctx.user, err => {\n if (err) {\n _ack(err)\n return\n }\n\n const _ctxid = utils.text.random()\n const chain = [{item: item, soul: soul}]\n // Pass on the previous ctx's callback and user flag here.\n allctx.set(_ctxid, {\n chain: chain,\n user: ctx.user,\n cb: ctx.cb,\n })\n api(_ctxid).put(data)\n })\n return\n }\n\n const update = []\n for (const key of result) {\n const err = await new Promise(res => {\n if (utils.obj.is(data[key]) && !utils.rel.is(data[key])) {\n // Use the current rel as the context for nested objects.\n const _ctxid = utils.text.random()\n const chain = [{item: key, soul: id}]\n allctx.set(_ctxid, {chain: chain, user: ctx.user})\n api(_ctxid).put(data[key], res)\n } else {\n // Group the rest of the updates for put below.\n update.push(key)\n res(null)\n }\n })\n if (err) {\n _ack(err, ctxid)\n return\n }\n }\n\n if (update.length === 0) {\n _ack(null)\n return\n }\n\n // Only write the primitive update keys. Rels created by the\n // recursive puts above are already in the in-memory graph.\n const updateNode = {}\n update.forEach(key => {\n updateNode[key] = data[key]\n })\n const g = await graph(id, updateNode, ctx.user, _ack)\n if (g === null) return\n\n wire.put(g, _ack)\n },\n {secure: !!(ctx.user || opt.secure), put: true},\n )\n }\n attemptRead()\n },\n on: (lex, cb, _get, _opt) => {\n if (typeof lex === \"function\") {\n _opt = _get\n _get = cb\n cb = lex\n lex = null\n }\n if (typeof cb !== \"function\") {\n console.log(\"error on() requires a callback function\")\n return\n }\n\n if (!ctxid) {\n console.log(\"error please provide a key using get(key)\")\n cb(null)\n return\n }\n\n // Resolve the current context before adding event listener.\n const {item, soul} = resolve({on: lex, _get: _get, _opt: _opt}, cb)\n if (!soul) return\n\n // Get the context to check if it has user info\n const ctx = allctx.get(ctxid)\n\n // Flag that this context is set from on and shouldn't be removed.\n allctx.set(ctxid, {\n chain: [{item: item, soul: soul}],\n on: true,\n user: ctx ? ctx.user : null,\n })\n // Map the user's callback because it can also be passed to off,\n // so need a reference to it to compare them.\n // Shared retry state for this on() subscription.\n let retryCount = 0\n const maxRetries = 5\n const retryDelay = 1000 // Start with 1 second\n let retryTimer = null\n\n map.set(cb, () => {\n // Bail out if off() has already cleaned up this context \u2014 the mapped\n // callback can fire twice (once from wire.on and once from the _get\n // immediate-read path) and the second call after async context\n // cleanup would crash in resolve(). Matches the guard in watchForRel.\n if (!allctx.has(ctxid)) return\n // Cancel any pending retry \u2014 the persistent listener firing means we\n // have an update and should not call cb twice.\n clearTimeout(retryTimer)\n retryTimer = null\n // When listener fires, re-check if the item is now a rel.\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n const node = msg.put && msg.put[soul]\n const current = node && node[item]\n const id = utils.rel.is(current)\n if (id) {\n // It's a rel, read the related node. It might not be in the\n // graph yet when the listener fires, so we retry with delays.\n const attemptRead = async (retries = 0) => {\n const data = await new Promise(res => {\n const _ctxid = utils.text.random()\n allctx.set(_ctxid, {\n chain: [{item: null, soul: id}],\n user: ctx ? ctx.user : null,\n })\n api(_ctxid).next(\n null,\n res,\n retries === 0 ? utils.obj.put(_opt, \"fast\", true) : _opt,\n )\n })\n if (data !== null || retries >= 5) {\n retryCount = 0 // Reset retry counter on success\n cb(data)\n } else {\n // Data not ready, retry after delay\n await new Promise(resolve => setTimeout(resolve, 50))\n attemptRead(retries + 1)\n }\n }\n attemptRead()\n } else {\n // It's a direct property or null.\n const nodeExists = !!node\n\n if (nodeExists) {\n // Node exists \u2014 return the value and reset retry state.\n retryCount = 0\n cb(current !== undefined ? current : null)\n } else if (retryCount < maxRetries) {\n // No data yet \u2014 keep polling until we get a response or\n // exhaust retries. on() with _get can return null on a cache\n // miss and never fire again if the data doesn't change while\n // the listener is attached, so we must poll for initial load.\n const retry = () => {\n const delay = Math.min(\n retryDelay * Math.pow(2, retryCount),\n 30000,\n )\n retryCount++\n retryTimer = setTimeout(() => {\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n const retryNode = msg.put && msg.put[soul]\n if (retryNode) {\n retryCount = 0\n retryTimer = null\n const retryValue = retryNode[item]\n cb(retryValue !== undefined ? retryValue : null)\n } else if (retryCount < maxRetries) {\n retry()\n } else {\n retryTimer = null\n cb(null)\n }\n },\n {..._opt, secure: !!(ctx.user || opt.secure)},\n )\n }, delay)\n }\n retry()\n } else {\n cb(null)\n }\n }\n },\n {..._opt, secure: !!(ctx.user || opt.secure)},\n )\n })\n\n // Register listener immediately to avoid missing updates due to\n // queueing. Initially register the soul without _get, then update if\n // it's a rel.\n let initialLex\n if (lex) {\n initialLex = utils.obj.put(lex, \"#\", soul)\n // Normalize numeric property filters to strings for wire operations\n // Only convert if it's a number, not if it's a complex filter object\n if (initialLex[\".\"] != null && typeof initialLex[\".\"] === \"number\") {\n initialLex = {...initialLex, \".\": String(initialLex[\".\"])}\n }\n } else {\n initialLex = {\"#\": soul, \".\": item}\n }\n wire.on(initialLex, map.get(cb), false, _opt)\n\n // Check if item is a rel and update listener if needed.\n // This happens async but the listener is already registered above.\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n if (msg.err) {\n console.log(`error getting ${soul}.${item}: ${msg.err}`)\n return\n }\n\n const current = msg.put && msg.put[soul] && msg.put[soul][item]\n const id = utils.rel.is(current)\n if (id) {\n // It's a rel, need to switch listener to the related node\n // First remove the initial listener\n wire.off(initialLex, map.get(cb))\n // Then add listener on the related node\n wire.on({\"#\": id, \".\": null}, map.get(cb), false, _opt)\n if (_get) map.get(cb)()\n } else if (_get) {\n // Not a rel, but _get was requested, so trigger callback.\n map.get(cb)()\n }\n },\n {..._opt, secure: !!(ctx.user || opt.secure)},\n )\n },\n off: cb => {\n if (!ctxid) {\n console.log(\"error please provide a key using get(key)\")\n if (cb) cb(null)\n return\n }\n\n // Resolve the current context before removing event listener.\n const {item, soul} = resolve({off: true}, cb)\n if (!soul) return\n\n // Remove listener immediately from the original soul to avoid a race\n // condition. The listener may be on a related soul if item is a rel,\n // but we remove from the original soul first since that's where it's\n //initially registered.\n wire.off({\"#\": soul}, map.get(cb))\n\n // Check if item is a rel and remove from the related node as well.\n wire.get({\"#\": soul, \".\": item}, msg => {\n if (msg.err) {\n // Even if get fails, we've already removed from original soul\n map.delete(cb)\n allctx.delete(ctxid)\n return\n }\n\n const current = msg.put && msg.put[soul] && msg.put[soul][item]\n const id = utils.rel.is(current)\n if (id) wire.off({\"#\": id}, map.get(cb))\n map.delete(cb)\n allctx.delete(ctxid)\n })\n },\n user: () => {\n if (!user.get) {\n // Return the combined Holster and User APIs.\n Object.assign(user, api())\n // Need to provide a user specific get() function to know if user\n // context should be checked.\n user.get = (keys, lex, cb, _opt) => {\n if (typeof lex === \"function\") {\n _opt = cb\n cb = lex\n lex = null\n }\n\n let pub = null\n let key = null\n if (user.is) pub = user.is.pub\n if (typeof keys === \"string\") {\n key = keys\n } else if (keys instanceof Array) {\n if (keys.length === 2) {\n pub = keys[0]\n key = keys[1]\n } else if (keys.length === 1) {\n key = keys[0]\n }\n }\n if (!pub) {\n console.log(\"error please log in or provide a public key\")\n if (cb) cb(null)\n return\n }\n\n if (key === null || key === \"\" || key === \"_\") {\n console.log(\"error please provide a key\")\n if (cb) cb(null)\n return\n }\n\n // lex requires a callback as it's not included in the chain below.\n if (lex && !cb) {\n console.log(\"error lex requires a callback function\")\n return\n }\n\n ctxid = utils.text.random()\n const chain = [{item: String(key), soul: \"~\" + pub}]\n allctx.set(ctxid, {chain: chain, user: user.is, cb: cb})\n if (!cb) return api(ctxid)\n\n // When there's a callback need to resolve the context first.\n const _done = done(ctxid)\n const {soul} = resolve({get: lex, _opt: _opt}, _done)\n if (soul) get(lex, soul, _done, _opt)\n }\n }\n return user\n },\n // Allow the wire spec to be used via holster.\n wire: wire,\n // Allow SEA functions to be used via holster.\n SEA: SEA,\n }\n }\n return api()\n}\n\nexport default Holster\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["num", "n", "parsed", "obj", "o", "match", "list", "cb", "keys", "i", "result", "key", "value", "map_soul", "soul", "rel", "userSignature", "userPublicKey", "graph", "data", "sig", "pub", "timestamp", "g", "lex", "prefix", "gt", "lt", "text", "length", "s", "c", "Dup", "dup", "id", "now", "dup_default", "Get", "lex", "graph", "fast", "soul", "node", "signatures", "key", "state", "userPublicKey", "pkState", "found", "match", "get_default", "data", "SeaArray", "enc", "start", "end", "buf", "byte", "_", "i", "charCode", "utf8String", "array_default", "SECURITY_LIMITS", "SafeBuffer", "props", "validateStringInput", "input", "encoding", "validateBufferSize", "size", "operation", "parseHexString", "hexString", "cleanHex", "bytes", "i", "hexByte", "encodeUtf8String", "str", "err", "encodeBinaryString", "charCode", "parseBase64String", "base64String", "cleanBase64", "decodedString", "processArrayLikeInput", "val", "arr", "array_default", "length", "fill", "buffer", "totalLength", "validatedBuffers", "item", "result", "offset", "obj", "string", "clean", "start", "end", "buffer_default", "isNode", "crypto", "subtle", "stringify", "data", "parse", "text", "random", "length", "array", "buffer_default", "jwk", "pub", "priv", "x", "y", "sha256", "hash", "aeskey", "key", "salt", "combined", "keyToJwk", "SEA", "cb", "ecdsa", "subtle", "keys", "pub", "ecdh", "pair", "data", "rand", "random", "ct", "aeskey", "aes", "stringify", "enc", "buffer_default", "dec", "parse", "signed", "key", "jwk", "msg", "k", "userPublicKey", "userSignature", "hash", "sha256", "sig", "alg", "verified", "check", "timestamp", "timestampStr", "signature", "publicKey", "isValid", "err", "salt", "work", "to", "from", "pubKey", "priv", "derived", "derivedBits", "derivedKey", "sea_default", "MAX_GRAPH_SIZE", "Ham", "state", "currentState", "value", "currentValue", "signed", "change", "graph", "hasNode", "secure", "listen", "maxGraphSize", "machine", "now", "defer", "listeners", "validProperties", "validTimestamps", "wait", "soul", "node", "updated", "alias", "nodeWait", "verify", "pub", "userPublicKey", "signedTimestamps", "signedProperties", "incomingTimestamps", "key", "sig", "asNumber", "propsForTimestamp", "ts", "prop", "sea_default", "rel", "skew", "isSigned", "l", "match", "souls", "states", "maxState", "a", "b", "ham_default", "group", "record", "Radix", "radix", "keys", "value", "tree", "i", "tmp", "key", "max", "noValue", "found", "obj", "hasValue", "hasKey", "j", "matchingKey", "bestKey", "bestMatch", "replace", "map", "cb", "opt", "pre", "u", "radix_default", "etx", "enq", "unit", "Radisk", "opt", "u", "cache", "fileListCache", "fileListCacheTime", "FILE_LIST_CACHE_TTL", "pendingReads", "lastMemoryCheck", "MEMORY_CHECK_INTERVAL", "HEAP_WARNING_THRESHOLD", "HEAP_CLEANUP_THRESHOLD", "checkMemoryUsage", "now", "memUsage", "heapUsed", "heapTotal", "maxHeapSize", "heapUsageRatio", "cacheSize", "radisk", "key", "value", "cb", "timeout", "callbacks", "callback", "err", "result", "radix_default", "batch", "rad", "save", "tree", "files", "file", "candidate", "start", "end", "disk", "pending", "firstErr", "settle", "write", "k", "pre", "enc", "validBoundary", "fullKey", "soul", "findFile", "lo", "hi", "mid", "read", "parse", "data", "preString", "tmp", "i", "a", "o", "state", "sig", "current", "text", "rel", "num", "obj", "previous", "textStart", "textEnd", "parts", "radisk_default", "isNode", "fs", "enq", "unit", "root", "fileSystem", "opt", "dir", "file", "cb", "err", "data", "tmp", "text", "files", "db", "dbReady", "resolve", "reject", "o", "event", "req", "_get", "_put", "_list", "Store", "obj", "radisk", "radisk_default", "lex", "soul", "key", "node", "signatures", "each", "value", "k", "userPublicKey", "match", "needsPubKey", "pending", "cbErr", "finish", "graph", "radix_default", "count", "finished", "ack", "state", "sig", "store_default", "Store", "isNode", "wsModule", "fs", "createRateLimiter", "isTestEnv", "clients", "maxRequests", "windowMs", "disconnectThreshold", "cleanupInterval", "now", "clientId", "data", "time", "client", "oldestRequest", "delay", "validRequests", "safeJSONParse", "maxSize", "error", "validateMessage", "createConnectionManager", "maxConnections", "connections", "ws", "originalClose", "args", "createRetryHandler", "maxRetries", "retryCount", "Wire", "opt", "dup", "dup_default", "store", "store_default", "graph", "queue", "listen", "hasNode", "pendingReferences", "recentChecks", "recentCheckTTL", "pendingTimeouts", "offlineTimeouts", "hasSoul", "soul", "resolve", "err", "rateLimiter", "connectionManager", "defaultLimit", "userStorage", "userLimits", "saveStorageTimer", "loadUserStorage", "cb", "raw", "pub", "total", "saveUserStorage", "t", "loadUserLimits", "limit", "formatBytes", "bytes", "logStorageSummary", "userCount", "defLimitStr", "sorted", "a", "b", "logUser", "limitStr", "check", "send", "key", "userPublicKey", "node", "msg", "res", "getWithCallback", "existing", "get", "ack", "get_default", "text", "put", "oldGraphBytes", "update", "ham_default", "finish", "toStore", "oldBytes", "newBytes", "lex", "_opt", "obj", "fast", "track", "request", "checkKey", "lastCheck", "sendResult", "value", "state", "match", "id", "api", "
|
|
3
|
+
"sources": ["../src/utils.js", "../src/dup.js", "../src/get.js", "../src/array.js", "../src/buffer.js", "../src/sea-utils.js", "../src/sea.js", "../src/ham.js", "../src/radix.js", "../src/radisk.js", "../src/store.js", "../src/wire.js", "../src/user.js", "../src/nested.js", "../src/holster.js"],
|
|
4
|
+
"sourcesContent": ["export const num = {\n is: n => {\n if (n instanceof Array) return false\n\n if (typeof n === \"number\") return !isNaN(n)\n\n if (typeof n === \"string\") {\n const parsed = parseFloat(n)\n return !isNaN(parsed) && isFinite(parsed)\n }\n\n return false\n },\n}\n\nexport const obj = {\n is: o => {\n if (!o || typeof o !== \"object\") return false\n\n const toString = Object.prototype.toString.call(o)\n const match = toString.match(/^\\[object (\\w+)\\]$/)\n return o.constructor === Object || (match && match[1] === \"Object\")\n },\n map: (list, cb, o) => {\n var keys = Object.keys(list)\n for (let i = 0; i < keys.length; i++) {\n let result = cb(list[keys[i]], keys[i], o)\n if (typeof result !== \"undefined\") return result\n }\n },\n put: (o, key, value) => {\n if (!o) o = {}\n o[key] = value\n return o\n },\n del: (o, key) => {\n if (!o) return\n\n o[key] = null\n delete o[key]\n return o\n },\n}\n\nconst map_soul = (soul, key, o) => {\n // If id is already defined AND we're still looping through the object,\n // then it is considered invalid.\n if (o.id) {\n o.id = false\n return\n }\n\n if (key === \"#\" && typeof soul === \"string\") {\n o.id = soul\n return\n }\n\n // If there exists anything else on the object that isn't the soul,\n // then it is considered invalid.\n o.id = false\n}\n\n// Check if an object is a soul relation, ie {'#': 'UUID'}\nexport const rel = {\n is: value => {\n if (value && value[\"#\"] && !value._ && obj.is(value)) {\n let o = {}\n obj.map(value, map_soul, o)\n if (o.id) return o.id\n }\n\n return false\n },\n // Convert a soul into a relation and return it.\n ify: soul => obj.put({}, \"#\", soul),\n}\n\nexport const userSignature = \"_holster_user_signature\"\nexport const userPublicKey = \"_holster_user_public_key\"\n\n// graph converts objects to graph format with updated states,\n// with optional meta data to verify signed data.\nexport const graph = (soul, data, sig, pub, timestamp) => {\n const g = {[soul]: {_: {\"#\": soul, \">\": {}}}}\n\n for (const [key, value] of Object.entries(data)) {\n if (key !== \"_\" && key !== userPublicKey && key !== userSignature) {\n g[soul][key] = value\n g[soul]._[\">\"][key] = timestamp || Date.now()\n }\n }\n if (sig && pub && timestamp) {\n g[soul]._[\"s\"] = {[timestamp]: sig}\n g[soul][userPublicKey] = pub\n g[soul]._[\">\"][userPublicKey] = timestamp\n }\n return g\n}\n\nexport const match = (lex, key) => {\n // Null is used to match listeners on souls, which don't provide a key.\n if (typeof key === \"undefined\") return lex === null\n\n if (typeof lex === \"undefined\") return true\n\n if (typeof lex === \"string\") return lex === key\n\n // Array support: check if key is in the array\n if (Array.isArray(lex)) return lex.includes(key)\n\n if (!obj.is(lex) || !key) return false\n\n const prefix = lex[\"*\"]\n if (prefix) return key.slice(0, prefix.length) === prefix\n\n const gt = lex[\">\"]\n const lt = lex[\"<\"]\n if (gt && lt) return key >= gt && key <= lt\n\n if (gt) return key >= gt\n\n if (lt) return key <= lt\n\n return false\n}\n\nexport const text = {\n random: length => {\n var s = \"\"\n const c = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n if (!length) length = 24\n for (let i = 0; i < length; i++) {\n s += c.charAt(Math.floor(Math.random() * c.length))\n }\n return s\n },\n}\n", "const Dup = () => {\n const maxAge = 9000\n const dup = {store: {}}\n dup.check = id => (dup.store[id] ? dup.track(id) : false)\n dup.track = id => {\n // Keep the liveliness of the message up while it is being received.\n dup.store[id] = Date.now()\n if (!dup.expiry) {\n dup.expiry = setTimeout(() => {\n const now = Date.now()\n Object.keys(dup.store).forEach(id => {\n if (now - dup.store[id] > maxAge) delete dup.store[id]\n })\n dup.expiry = null\n }, maxAge)\n // Don't block process exit \u2014 cleanup is best-effort.\n if (dup.expiry.unref) dup.expiry.unref()\n }\n return id\n }\n return dup\n}\n\nexport default Dup\n", "import {match, userPublicKey} from \"./utils.js\"\n\nconst Get = (lex, graph, fast) => {\n if (!lex || typeof lex !== \"object\") {\n throw new TypeError(\"lex must be an object\")\n }\n if (!graph || typeof graph !== \"object\") {\n throw new TypeError(\"graph must be an object\")\n }\n\n const soul = lex[\"#\"]\n if (!soul || typeof soul !== \"string\") {\n throw new TypeError(\"soul must be a string\")\n }\n\n if (!graph[soul]) return\n\n const node = {_: {\"#\": soul, \">\": {}}}\n let signatures = {}\n\n if (typeof lex[\".\"] === \"string\") {\n const key = lex[\".\"]\n if (typeof graph[soul][key] === \"undefined\") return\n\n node[key] = graph[soul][key]\n node._[\">\"][key] = graph[soul]._[\">\"][key]\n const state = graph[soul]._[\">\"][key]\n if (graph[soul]._[\"s\"] && graph[soul]._[\"s\"][state]) {\n signatures[state] = graph[soul]._[\"s\"][state]\n }\n\n // Always include userPublicKey for verification, regardless of filter\n if (userPublicKey && typeof graph[soul][userPublicKey] !== \"undefined\") {\n node[userPublicKey] = graph[soul][userPublicKey]\n node._[\">\"][userPublicKey] = graph[soul]._[\">\"][userPublicKey]\n const pkState = graph[soul]._[\">\"][userPublicKey]\n if (graph[soul]._[\"s\"] && graph[soul]._[\"s\"][pkState]) {\n signatures[pkState] = graph[soul]._[\"s\"][pkState]\n }\n }\n } else {\n // For fast requests, return properties currently in the graph. Otherwise\n // return undefined to ensure we get all matching properties from store.\n if (!fast) return\n\n let found = false\n for (const key of Object.keys(graph[soul])) {\n // Always include userPublicKey for verification, regardless of filter\n if (key !== \"_\" && (key === userPublicKey || match(lex[\".\"], key))) {\n node[key] = graph[soul][key]\n node._[\">\"][key] = graph[soul]._[\">\"][key]\n const state = graph[soul]._[\">\"][key]\n if (graph[soul]._[\"s\"] && graph[soul]._[\"s\"][state]) {\n signatures[state] = graph[soul]._[\"s\"][state]\n }\n found = true\n }\n }\n if (!found) return\n }\n if (Object.keys(signatures).length > 0) {\n node._[\"s\"] = signatures\n }\n return {[soul]: node}\n}\n\nexport default Get\n", "if (typeof btoa === \"undefined\") {\n globalThis.btoa = data => Buffer.from(data, \"binary\").toString(\"base64\")\n globalThis.atob = data => Buffer.from(data, \"base64\").toString(\"binary\")\n}\n\n// This is Array extended to have .toString([\"utf8\"|\"hex\"|\"base64\"])\nfunction SeaArray() {}\nObject.assign(SeaArray, {from: Array.from})\nSeaArray.prototype = Object.create(Array.prototype)\n\nSeaArray.prototype.toString = function (enc, start, end) {\n if (!enc) enc = \"utf8\"\n if (!start) start = 0\n\n end = end ? Math.min(Math.max(end, start), this.length) : this.length\n\n if (enc === \"hex\") {\n const buf = new Uint8Array(this.slice(start, end))\n return Array.from(buf, byte => byte.toString(16).padStart(2, \"0\")).join(\"\")\n }\n\n if (enc === \"utf8\") {\n return Array.from({length: end - start}, (_, i) => {\n const charCode = this[i + start]\n // Use unicode replacement character for invalid character codes.\n if (charCode < 0 || charCode > 0x10ffff) {\n return String.fromCharCode(0xfffd)\n }\n return String.fromCharCode(charCode)\n }).join(\"\")\n }\n\n if (enc === \"base64\") {\n const utf8String = Array.from({length: end - start}, (_, i) => {\n const charCode = this[i + start]\n if (charCode < 0 || charCode > 255) {\n return String.fromCharCode(0xfffd)\n }\n return String.fromCharCode(charCode)\n }).join(\"\")\n return btoa(utf8String)\n }\n}\n\nexport default SeaArray\n", "import SeaArray from \"./array.js\"\n\n// Security constants\nconst SECURITY_LIMITS = {\n MAX_BUFFER_SIZE: 10 * 1024 * 1024, // 10MB limit\n MAX_STRING_LENGTH: 1024 * 1024, // 1MB string limit\n}\n\n// Secure Buffer implementation for SEA.js\n// Compatible with NodeJS safe-buffer but with enhanced security\nfunction SafeBuffer(...props) {\n console.warn(\"new SafeBuffer() is deprecated, please use SafeBuffer.from()\")\n return SafeBuffer.from(...props)\n}\n\nSafeBuffer.prototype = Object.create(Array.prototype)\n\n// Input validation helpers\nconst validateStringInput = (input, encoding) => {\n if (typeof input !== \"string\") {\n throw new TypeError(\"Input must be a string for encoding: \" + encoding)\n }\n\n if (input.length > SECURITY_LIMITS.MAX_STRING_LENGTH) {\n throw new RangeError(\n `String too large: ${input.length} > ${SECURITY_LIMITS.MAX_STRING_LENGTH}`,\n )\n }\n}\n\nconst validateBufferSize = (size, operation = \"buffer operation\") => {\n if (size > SECURITY_LIMITS.MAX_BUFFER_SIZE) {\n throw new RangeError(\n `Buffer size too large for ${operation}: ${size} > ${SECURITY_LIMITS.MAX_BUFFER_SIZE}`,\n )\n }\n}\n\n// Secure hex parsing\nconst parseHexString = hexString => {\n validateStringInput(hexString, \"hex\")\n\n // Remove any whitespace and convert to lowercase\n const cleanHex = hexString.replace(/\\s/g, \"\").toLowerCase()\n\n // Validate hex format: only 0-9, a-f characters\n if (!/^[0-9a-f]*$/.test(cleanHex)) {\n throw new TypeError(\"Invalid hex string: contains non-hex characters\")\n }\n\n // Must be even length\n if (cleanHex.length % 2 !== 0) {\n throw new TypeError(\"Invalid hex string: must have even length\")\n }\n\n if (cleanHex.length === 0) {\n return new Uint8Array(0)\n }\n\n validateBufferSize(cleanHex.length / 2, \"hex parsing\")\n\n const bytes = new Uint8Array(cleanHex.length / 2)\n for (let i = 0; i < cleanHex.length; i += 2) {\n const hexByte = cleanHex.substr(i, 2)\n bytes[i / 2] = parseInt(hexByte, 16)\n }\n return bytes\n}\n\nconst encodeUtf8String = str => {\n validateStringInput(str, \"utf8\")\n\n try {\n // Use standard TextEncoder for proper UTF-8 encoding\n const encoder = new TextEncoder()\n const bytes = encoder.encode(str)\n\n validateBufferSize(bytes.length, \"UTF-8 encoding\")\n return bytes\n } catch (err) {\n throw new TypeError(\"Failed to encode UTF-8 string: \" + err.message)\n }\n}\n\nconst encodeBinaryString = str => {\n validateStringInput(str, \"binary\")\n\n validateBufferSize(str.length, \"binary encoding\")\n\n const bytes = new Uint8Array(str.length)\n for (let i = 0; i < str.length; i++) {\n const charCode = str.charCodeAt(i)\n\n // Binary strings should only contain bytes (0-255)\n if (charCode > 255) {\n throw new TypeError(\n `Invalid binary string: character at position ${i} exceeds byte range (${charCode} > 255)`,\n )\n }\n\n bytes[i] = charCode\n }\n return bytes\n}\n\n// Secure base64 decoding\nconst parseBase64String = base64String => {\n validateStringInput(base64String, \"base64\")\n\n // Remove any whitespace\n const cleanBase64 = base64String.replace(/\\s/g, \"\")\n\n // Validate base64 format\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleanBase64)) {\n throw new TypeError(\"Invalid base64 string: contains invalid characters\")\n }\n\n try {\n const decodedString = atob(cleanBase64)\n validateBufferSize(decodedString.length, \"base64 decoding\")\n\n const bytes = new Uint8Array(decodedString.length)\n for (let i = 0; i < decodedString.length; i++) {\n bytes[i] = decodedString.charCodeAt(i)\n }\n\n return bytes\n } catch (err) {\n throw new TypeError(\"Failed to decode base64 string: \" + err.message)\n }\n}\n\n// Secure array-like input processing\nconst processArrayLikeInput = input => {\n let bytes\n\n if (input instanceof ArrayBuffer) {\n validateBufferSize(input.byteLength, \"ArrayBuffer processing\")\n bytes = new Uint8Array(input)\n } else if (ArrayBuffer.isView(input)) {\n validateBufferSize(\n input.byteLength || input.length,\n \"TypedArray processing\",\n )\n bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength)\n } else if (Array.isArray(input)) {\n validateBufferSize(input.length, \"Array processing\")\n\n // Validate all array elements are valid byte values\n for (let i = 0; i < input.length; i++) {\n const val = input[i]\n if (\n typeof val !== \"number\" ||\n val < 0 ||\n val > 255 ||\n !Number.isInteger(val)\n ) {\n throw new TypeError(\n `Invalid byte value at index ${i}: ${val} (must be integer 0-255)`,\n )\n }\n }\n\n bytes = new Uint8Array(input)\n } else if (\n typeof input === \"object\" &&\n input !== null &&\n typeof input.byteLength === \"number\"\n ) {\n // Handle ArrayBuffer from different contexts (e.g. jsdom)\n validateBufferSize(input.byteLength, \"ArrayBuffer-like processing\")\n bytes = new Uint8Array(input)\n } else if (\n typeof input === \"object\" &&\n input !== null &&\n typeof input.length === \"number\"\n ) {\n // Handle array-like objects\n validateBufferSize(input.length, \"array-like processing\")\n\n const arr = Array.from(input)\n for (let i = 0; i < arr.length; i++) {\n const val = arr[i]\n if (\n typeof val !== \"number\" ||\n val < 0 ||\n val > 255 ||\n !Number.isInteger(val)\n ) {\n throw new TypeError(\n `Invalid byte value at index ${i}: ${val} (must be integer 0-255)`,\n )\n }\n }\n bytes = new Uint8Array(arr)\n } else {\n throw new TypeError(\"Unsupported input type: \" + typeof input)\n }\n\n return bytes\n}\n\nObject.assign(SafeBuffer, {\n from() {\n const argCount = arguments.length\n\n if (argCount === 0) {\n throw new TypeError(\"SafeBuffer.from() requires at least one argument\")\n }\n\n const input = arguments[0]\n\n if (input === null || input === undefined) {\n throw new TypeError(\"First argument must not be null or undefined\")\n }\n\n let bytes\n\n if (typeof input === \"string\") {\n const encoding = (arguments[1] || \"utf8\").toLowerCase()\n\n switch (encoding) {\n case \"hex\":\n bytes = parseHexString(input)\n break\n\n case \"utf8\":\n case \"utf-8\":\n bytes = encodeUtf8String(input)\n break\n\n case \"binary\":\n case \"latin1\":\n bytes = encodeBinaryString(input)\n break\n\n case \"base64\":\n bytes = parseBase64String(input)\n break\n\n case \"ascii\":\n // ASCII is subset of UTF-8, but validate range\n validateStringInput(input, \"ascii\")\n for (let i = 0; i < input.length; i++) {\n if (input.charCodeAt(i) > 127) {\n throw new TypeError(\n `Invalid ASCII character at position ${i}: ${input.charCodeAt(i)} > 127`,\n )\n }\n }\n bytes = encodeUtf8String(input) // Safe since ASCII is UTF-8 subset\n break\n\n default:\n throw new TypeError(\"Unknown encoding: \" + encoding)\n }\n } else {\n bytes = processArrayLikeInput(input)\n }\n\n if (!bytes || bytes.length === 0) {\n return SeaArray.from(new Uint8Array(0))\n }\n\n try {\n return SeaArray.from(bytes)\n } catch (err) {\n throw new Error(\"Failed to create SafeBuffer: \" + err.message)\n }\n },\n\n alloc(length, fill = 0) {\n if (typeof length !== \"number\" || !Number.isInteger(length) || length < 0) {\n throw new TypeError(\"Length must be a non-negative integer\")\n }\n\n validateBufferSize(length, \"buffer allocation\")\n\n // Validate fill value\n if (typeof fill === \"number\") {\n if (fill < 0 || fill > 255 || !Number.isInteger(fill)) {\n throw new TypeError(\"Fill value must be an integer between 0 and 255\")\n }\n } else if (typeof fill === \"string\") {\n if (fill.length !== 1) {\n throw new TypeError(\"Fill string must be exactly one character\")\n }\n fill = fill.charCodeAt(0)\n if (fill > 255) {\n throw new TypeError(\"Fill character code must be <= 255\")\n }\n } else {\n throw new TypeError(\"Fill must be a number or single character string\")\n }\n\n try {\n const buffer = new Uint8Array(length)\n if (fill !== 0) {\n buffer.fill(fill)\n }\n return SeaArray.from(buffer)\n } catch (err) {\n throw new Error(\"Failed to allocate buffer: \" + err.message)\n }\n },\n\n concat(arr) {\n if (!Array.isArray(arr)) {\n throw new TypeError(\"First argument must be an array\")\n }\n\n if (arr.length === 0) {\n return SeaArray.from(new Uint8Array(0))\n }\n\n // Validate all array elements and calculate total size\n let totalLength = 0\n const validatedBuffers = []\n\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i]\n\n if (!item) {\n throw new TypeError(`Array element at index ${i} is null or undefined`)\n }\n\n let bytes\n try {\n bytes = processArrayLikeInput(item)\n } catch (err) {\n throw new TypeError(\n `Invalid array element at index ${i}: ${err.message}`,\n )\n }\n\n totalLength += bytes.length\n validateBufferSize(totalLength, \"buffer concatenation\")\n\n validatedBuffers.push(bytes)\n }\n\n try {\n const result = new Uint8Array(totalLength)\n let offset = 0\n\n for (const buffer of validatedBuffers) {\n result.set(buffer, offset)\n offset += buffer.length\n }\n\n return SeaArray.from(result)\n } catch (err) {\n throw new Error(\"Failed to concatenate buffers: \" + err.message)\n }\n },\n\n // Helper method to check if object is SafeBuffer\n isBuffer(obj) {\n return (\n obj instanceof SeaArray ||\n (obj && typeof obj === \"object\" && obj.constructor === SafeBuffer)\n )\n },\n\n // Get byte length of string in specific encoding\n byteLength(string, encoding = \"utf8\") {\n if (typeof string !== \"string\") {\n throw new TypeError(\"First argument must be a string\")\n }\n\n switch (encoding.toLowerCase()) {\n case \"utf8\":\n case \"utf-8\":\n return new TextEncoder().encode(string).length\n\n case \"ascii\":\n case \"binary\":\n case \"latin1\":\n return string.length\n\n case \"base64\":\n const clean = string.replace(/\\s/g, \"\")\n return (\n Math.floor((clean.length * 3) / 4) - (clean.match(/=/g) || []).length\n )\n\n case \"hex\":\n return Math.floor(string.replace(/\\s/g, \"\").length / 2)\n\n default:\n throw new TypeError(\"Unknown encoding: \" + encoding)\n }\n },\n})\n\nSafeBuffer.prototype.from = SafeBuffer.from\nSafeBuffer.prototype.toString = function (\n encoding = \"utf8\",\n start = 0,\n end = this.length,\n) {\n // Input validation\n if (typeof encoding !== \"string\") {\n throw new TypeError(\"Encoding must be a string\")\n }\n\n if (typeof start !== \"number\" || !Number.isInteger(start) || start < 0) {\n throw new TypeError(\"Start must be a non-negative integer\")\n }\n\n if (typeof end !== \"number\" || !Number.isInteger(end) || end < start) {\n throw new TypeError(\"End must be an integer >= start\")\n }\n\n // Delegate to SeaArray with validation\n try {\n return SeaArray.prototype.toString.call(this, encoding, start, end)\n } catch (err) {\n throw new Error(\"Failed to convert buffer to string: \" + err.message)\n }\n}\n\nexport default SafeBuffer\n", "import SafeBuffer from \"./buffer.js\"\n\nconst isNode = typeof process !== \"undefined\" && process.versions?.node != null\nconst crypto = isNode\n ? (await import(/*webpackIgnore: true*/ \"node:crypto\")).webcrypto\n : globalThis.crypto\nexport const subtle = crypto.subtle\n\nexport const stringify = data => {\n return typeof data === \"string\" ? data : JSON.stringify(data)\n}\n\nexport const parse = text => {\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nexport const random = length => {\n const array = new Uint8Array(SafeBuffer.alloc(length))\n return SafeBuffer.from(crypto.getRandomValues(array))\n}\n\nexport const jwk = (pub, priv) => {\n const [x, y] = pub.split(\".\")\n const ops = priv ? [\"sign\"] : [\"verify\"]\n return {\n kty: \"EC\",\n crv: \"P-256\",\n x: x,\n y: y,\n d: priv,\n ext: true,\n key_ops: ops,\n }\n}\n\nexport const sha256 = async data => {\n const hash = await subtle.digest(\n {name: \"SHA-256\"},\n new TextEncoder().encode(stringify(data)),\n )\n return SafeBuffer.from(hash)\n}\n\nexport const aeskey = async (key, salt) => {\n const combined = key + salt.toString(\"utf8\")\n const hash = SafeBuffer.from(await sha256(combined), \"binary\")\n const jwk = keyToJwk(hash)\n return await subtle.importKey(\"jwk\", jwk, {name: \"AES-GCM\"}, false, [\n \"encrypt\",\n \"decrypt\",\n ])\n}\n\nconst keyToJwk = key => {\n const k = key\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/\\=/g, \"\")\n return {kty: \"oct\", k: k, ext: false, alg: \"A256GCM\"}\n}\n", "import {userPublicKey, userSignature} from \"./utils.js\"\nimport * as utils from \"./sea-utils.js\"\nimport SafeBuffer from \"./buffer.js\"\n\n// Security, Encryption, and Authorization: SEA.js from GunDB.\nconst SEA = {\n pair: async cb => {\n // ECDSA keys for signing/verifying.\n const ecdsa = await utils.subtle\n .generateKey({name: \"ECDSA\", namedCurve: \"P-256\"}, true, [\n \"sign\",\n \"verify\",\n ])\n .then(async keys => {\n const pub = await utils.subtle.exportKey(\"jwk\", keys.publicKey)\n return {\n priv: (await utils.subtle.exportKey(\"jwk\", keys.privateKey)).d,\n pub: pub.x + \".\" + pub.y,\n }\n })\n\n // ECDH keys for encryption/decryption.\n const ecdh = await utils.subtle\n .generateKey({name: \"ECDH\", namedCurve: \"P-256\"}, true, [\"deriveKey\"])\n .then(async keys => {\n const pub = await utils.subtle.exportKey(\"jwk\", keys.publicKey)\n return {\n epriv: (await utils.subtle.exportKey(\"jwk\", keys.privateKey)).d,\n epub: pub.x + \".\" + pub.y,\n }\n })\n\n const pair = {\n pub: ecdsa.pub,\n priv: ecdsa.priv,\n epub: ecdh.epub,\n epriv: ecdh.epriv,\n }\n if (cb) cb(pair)\n return pair\n },\n encrypt: async (data, pair, cb) => {\n if (!pair || !pair.epriv) {\n if (cb) cb(null)\n return null\n }\n\n const rand = {s: utils.random(9), iv: utils.random(15)}\n const ct = await utils.aeskey(pair.epriv, rand.s).then(aes => {\n return utils.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv: new Uint8Array(rand.iv),\n },\n aes,\n new TextEncoder().encode(utils.stringify(data)),\n )\n })\n const enc = {\n ct: SafeBuffer.from(ct, \"binary\").toString(\"base64\"),\n iv: rand.iv.toString(\"base64\"),\n s: rand.s.toString(\"base64\"),\n }\n if (cb) cb(enc)\n return enc\n },\n decrypt: async (enc, pair, cb) => {\n if (!enc || !enc.ct || !enc.iv || !enc.s || !pair || !pair.epriv) {\n if (cb) cb(null)\n return null\n }\n\n const data = {\n ct: SafeBuffer.from(enc.ct, \"base64\"),\n iv: SafeBuffer.from(enc.iv, \"base64\"),\n s: SafeBuffer.from(enc.s, \"base64\"),\n }\n try {\n const ct = await utils.aeskey(pair.epriv, data.s).then(aes => {\n return utils.subtle.decrypt(\n {\n name: \"AES-GCM\",\n iv: new Uint8Array(data.iv),\n tagLength: 128,\n },\n aes,\n new Uint8Array(data.ct),\n )\n })\n const dec = utils.parse(new TextDecoder(\"utf8\").decode(ct))\n if (cb) cb(dec)\n return dec\n } catch (err) {\n // An error will be thrown if the wrong key is used.\n if (cb) cb(null)\n return null\n }\n },\n verify: async (data, pair, cb) => {\n if (!pair || !pair.pub) {\n if (cb) cb(null)\n return null\n }\n\n const signed = utils.parse(data)\n const key = await utils.subtle.importKey(\n \"jwk\",\n utils.jwk(pair.pub),\n {name: \"ECDSA\", namedCurve: \"P-256\"},\n false,\n [\"verify\"],\n )\n\n let msg = {}\n if (typeof signed.m === \"string\") {\n msg = signed.m\n } else {\n // Allow data to be passed in with graph meta data,\n // (which should not be part of signature, so not verified).\n for (const k of Object.keys(signed.m).sort()) {\n if (k !== \"_\" && k !== userPublicKey && k !== userSignature) {\n msg[k] = signed.m[k]\n }\n }\n }\n const hash = await utils.sha256(msg)\n const sig = new Uint8Array(SafeBuffer.from(signed.s, \"base64\"))\n const alg = {name: \"ECDSA\", hash: {name: \"SHA-256\"}}\n if (await utils.subtle.verify(alg, key, sig, new Uint8Array(hash))) {\n const verified = utils.parse(signed.m)\n if (cb) cb(verified)\n return verified\n }\n\n if (cb) cb(null)\n return null\n },\n sign: async (data, pair, cb) => {\n if (!pair || !pair.pub || !pair.priv) {\n if (cb) cb(null)\n return null\n }\n\n let msg = {}\n if (typeof data === \"string\") {\n msg = data\n } else {\n const check = utils.parse(data)\n for (const k of Object.keys(check).sort()) {\n if (k !== \"_\" && k !== userPublicKey && k !== userSignature) {\n msg[k] = check[k]\n }\n }\n }\n const hash = await utils.sha256(msg)\n const jwk = utils.jwk(pair.pub, pair.priv)\n const alg = {name: \"ECDSA\", namedCurve: \"P-256\"}\n const sig = await utils.subtle\n .importKey(\"jwk\", jwk, alg, false, [\"sign\"])\n .then(key =>\n utils.subtle.sign(\n {name: \"ECDSA\", hash: {name: \"SHA-256\"}},\n key,\n new Uint8Array(hash),\n ),\n )\n const signed = {\n m: msg,\n s: SafeBuffer.from(sig, \"binary\").toString(\"base64\"),\n }\n\n if (cb) cb(signed)\n return signed\n },\n // Sign a timestamp to prove ownership of an update\n signTimestamp: async (timestamp, pair, cb) => {\n if (!pair || !pair.pub || !pair.priv) {\n if (cb) cb(null)\n return null\n }\n\n // Convert timestamp to string for consistent hashing\n const timestampStr = timestamp.toString()\n const hash = await utils.sha256(timestampStr)\n const jwk = utils.jwk(pair.pub, pair.priv)\n const alg = {name: \"ECDSA\", namedCurve: \"P-256\"}\n\n const sig = await utils.subtle\n .importKey(\"jwk\", jwk, alg, false, [\"sign\"])\n .then(key =>\n utils.subtle.sign(\n {name: \"ECDSA\", hash: {name: \"SHA-256\"}},\n key,\n new Uint8Array(hash),\n ),\n )\n\n const signature = SafeBuffer.from(sig, \"binary\").toString(\"base64\")\n\n if (cb) cb(signature)\n return signature\n },\n // Verify a timestamp signature to confirm ownership of update\n verifyTimestamp: async (timestamp, signature, publicKey, cb) => {\n if (!publicKey || !timestamp || !signature) {\n if (cb) cb(false)\n return false\n }\n\n try {\n // Convert timestamp to string for consistent hashing\n const timestampStr = timestamp.toString()\n const hash = await utils.sha256(timestampStr)\n\n const key = await utils.subtle.importKey(\n \"jwk\",\n utils.jwk(publicKey),\n {name: \"ECDSA\", namedCurve: \"P-256\"},\n false,\n [\"verify\"],\n )\n\n const sig = new Uint8Array(SafeBuffer.from(signature, \"base64\"))\n const alg = {name: \"ECDSA\", hash: {name: \"SHA-256\"}}\n\n const isValid = await utils.subtle.verify(\n alg,\n key,\n sig,\n new Uint8Array(hash),\n )\n\n if (cb) cb(isValid)\n return isValid\n } catch (err) {\n console.log(`error verifying timestamp signature: ${err.message}`)\n if (cb) cb(false)\n return false\n }\n },\n work: async (data, salt, cb) => {\n if (typeof salt === \"function\") {\n cb = salt\n salt = undefined\n }\n if (typeof salt === \"undefined\") salt = utils.random(9)\n\n const key = await utils.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(utils.stringify(data)),\n {name: \"PBKDF2\"},\n false,\n [\"deriveBits\"],\n )\n const alg = {\n name: \"PBKDF2\",\n iterations: 100000,\n salt: new TextEncoder().encode(salt),\n hash: {name: \"SHA-256\"},\n }\n const work = await utils.subtle.deriveBits(alg, key, 512)\n // Use \"pair\" format so that work can be used as epriv by decrypt.\n const pair = {epriv: SafeBuffer.from(work, \"binary\").toString(\"base64\")}\n if (cb) cb(pair)\n return pair\n },\n secret: async (to, from, cb) => {\n if (!to || !to.epub || !from || !from.epub || !from.epriv) {\n if (cb) cb(null)\n return null\n }\n\n const alg = {name: \"ECDH\", namedCurve: \"P-256\"}\n const pub = utils.jwk(to.epub)\n const pubKey = await utils.subtle.importKey(\"jwk\", pub, alg, true, [])\n const priv = utils.jwk(from.epub, from.epriv, false)\n // utils.jwk provides default key_ops but it shouldn't be used here.\n delete priv.key_ops\n const derived = await utils.subtle\n .importKey(\"jwk\", priv, alg, false, [\"deriveBits\"])\n .then(async key => {\n const derivedBits = await utils.subtle.deriveBits(\n {public: pubKey, name: \"ECDH\", namedCurve: \"P-256\"},\n key,\n 256,\n )\n const derivedKey = await utils.subtle.importKey(\n \"raw\",\n new Uint8Array(derivedBits),\n {name: \"AES-GCM\", length: 256},\n true,\n [\"encrypt\", \"decrypt\"],\n )\n return utils.subtle.exportKey(\"jwk\", derivedKey).then(({k}) => k)\n })\n // Use \"pair\" format so that secret can be used as epriv by encrypt.\n if (cb) cb({epriv: derived})\n return {epriv: derived}\n },\n}\n\nexport default SEA\n", "import * as utils from \"./utils.js\"\nimport SEA from \"./sea.js\"\n\n// Maximum number of souls to keep in memory\nconst MAX_GRAPH_SIZE = 10000\n\n// state and value are the incoming changes.\n// currentState and currentValue are the current graph data.\nconst Ham = (state, currentState, value, currentValue, signed = false) => {\n if (state < currentState) return {historical: true}\n\n if (state > currentState) return {incoming: true}\n\n // state is equal to currentState. Old data is expected to propagate through\n // the network, but conflicting values with same signed timestamp are ignored\n // since the owner can only create one value per timestamp.\n if (signed && value !== currentValue) {\n return {historical: true}\n }\n\n // Lexically compare to resolve conflict (for unsigned or matching values)\n if (typeof value !== \"string\") {\n value = JSON.stringify(value) || \"\"\n }\n if (typeof currentValue !== \"string\") {\n currentValue = JSON.stringify(currentValue) || \"\"\n }\n // No update required.\n if (value === currentValue) return {state: true}\n\n // Keep the current value.\n if (value < currentValue) return {current: true}\n\n // Otherwise update using the incoming value.\n return {incoming: true}\n}\n\nHam.mix = async (\n change,\n graph,\n hasNode,\n secure,\n listen,\n maxGraphSize = MAX_GRAPH_SIZE,\n) => {\n if (!change || typeof change !== \"object\") {\n throw new TypeError(\"change must be an object\")\n }\n if (!graph || typeof graph !== \"object\") {\n throw new TypeError(\"graph must be an object\")\n }\n if (!listen || typeof listen !== \"object\") {\n throw new TypeError(\"listen must be an object\")\n }\n\n const machine = Date.now()\n const now = {}\n const defer = {}\n const listeners = [] // Collect listeners to fire after store.put\n const validProperties = new Map() // Track valid properties per soul\n const validTimestamps = new Map() // Track valid timestamps per soul\n let wait = 0\n\n for (const soul of Object.keys(change)) {\n const node = change[soul]\n let updated = false\n let alias = false\n let nodeWait = 0\n let verify = secure\n\n if (!node || !node._) continue\n\n const pub = node[utils.userPublicKey]\n // If timestamp signatures and public key are provided then always verify\n if (node._[\"s\"] && pub) verify = true\n\n // Special case if soul starts with \"~\". Node must be system data ie,\n // ~@alias or ~publickey. For aliases, key and value must be a self\n // identifying rel. For public keys, data needs to be signed and verified.\n // (This is also true for any data when the secure flag is used.)\n if (soul.length > 1 && soul[0] === \"~\") {\n if (soul[1] === \"@\") {\n alias = true\n verify = false\n } else {\n if (pub && soul != \"~\" + pub) {\n console.log(`error public key does not match for soul: ${soul}`)\n continue\n }\n\n verify = true\n }\n }\n if (verify) {\n // Signature verification: check node._[\"s\"] which can contain:\n // 1. Per-property signatures (legacy): keys are property names\n // 2. Timestamp signatures (new): keys are numeric timestamps\n if (!pub || !node._) {\n continue\n }\n\n const signedTimestamps = new Set()\n const signedProperties = new Set()\n\n // Skip verification of timestamps that are older than what's in the graph\n // to prevent old signatures from distributed messages causing conflicts\n const incomingTimestamps = Object.entries(node._[\">\"] || {})\n\n for (const [key, sig] of Object.entries(node._[\"s\"] || {})) {\n const asNumber = Number(key)\n if (!isNaN(asNumber) && asNumber > 0) {\n // Skip verification only if ALL properties for this timestamp are\n // already newer in the graph. Using some() would incorrectly skip\n // valid updates when only one property in a batch is outdated.\n const propsForTimestamp = incomingTimestamps.filter(\n ([, ts]) => Number(ts) === asNumber,\n )\n const allNewerInGraph =\n propsForTimestamp.length > 0 &&\n propsForTimestamp.every(([prop]) => {\n const graphState =\n graph[soul] && graph[soul]._[\">\"] ? graph[soul]._[\">\"][prop] : 0\n return graphState > asNumber\n })\n\n if (allNewerInGraph) {\n continue\n }\n\n const isValid = await SEA.verifyTimestamp(asNumber, sig, pub)\n if (isValid) {\n signedTimestamps.add(asNumber)\n // Add all properties with this timestamp to signed set\n for (const [prop, ts] of incomingTimestamps) {\n if (Number(ts) === asNumber) {\n signedProperties.add(prop)\n }\n }\n }\n }\n }\n\n // If no properties verified, skip this update\n if (signedProperties.size === 0) {\n continue\n }\n\n // Track signed properties and timestamps for this soul\n validProperties.set(soul, signedProperties)\n validTimestamps.set(soul, signedTimestamps)\n }\n\n for (const key of Object.keys(node)) {\n if (key === \"_\") continue\n\n // Properties without signatures in this update are left unchanged\n if (validProperties.has(soul) && !validProperties.get(soul).has(key)) {\n continue\n }\n\n const value = node[key]\n const state = node._ && node._[\">\"] ? node._[\">\"][key] : 0\n const currentValue = (graph[soul] || {})[key]\n const currentState = (graph[soul] || {_: {\">\": {}}})._[\">\"][key] || 0\n\n if (alias && key !== utils.rel.is(value)) {\n console.log(`error alias ${alias}: ${key} !== ${utils.rel.is(value)}`)\n continue\n }\n\n // Defer the update if ahead of machine time.\n const skew = state - machine\n if (skew > 0) {\n // Ignore update if ahead by more than 24 hours.\n if (skew > 86400000) continue\n\n // Wait the shortest difference before trying the updates again.\n if (wait === 0 || skew < wait) wait = nodeWait = skew\n if (!defer[soul]) {\n defer[soul] = {_: {\"#\": soul, \">\": {}, s: {}}}\n }\n defer[soul][key] = value\n defer[soul]._[\">\"][key] = state\n if (node._[\"s\"] && node._[\"s\"][state]) {\n defer[soul]._[\"s\"][state] = node._[\"s\"][state]\n }\n } else {\n // Check if this property has a signed timestamp\n const isSigned =\n validTimestamps.has(soul) && validTimestamps.get(soul).has(state)\n const result = Ham(state, currentState, value, currentValue, isSigned)\n if (result.incoming) {\n if (!now[soul]) {\n now[soul] = {_: {\"#\": soul, \">\": {}, s: {}}}\n }\n if (!graph[soul]) {\n graph[soul] = {_: {\"#\": soul, \">\": {}, s: {}}}\n }\n graph[soul][key] = now[soul][key] = value\n graph[soul]._[\">\"][key] = now[soul]._[\">\"][key] = state\n if (node._[\"s\"] && node._[\"s\"][state]) {\n graph[soul]._[\"s\"][state] = now[soul]._[\"s\"][state] =\n node._[\"s\"][state]\n }\n // Collect event listeners to fire after store.put completes.\n // This ensures listeners always fire with data that's been stored.\n if (listen[soul]) {\n listen[soul]\n .filter(l => utils.match(l[\".\"], key))\n .forEach(l => listeners.push(l.cb))\n }\n updated = true\n }\n }\n }\n\n // Collect event listeners for update on soul.\n if (updated && listen[soul]) {\n listen[soul]\n .filter(l => utils.match(l[\".\"]))\n .forEach(l => listeners.push(l.cb))\n }\n }\n\n const souls = Object.keys(graph)\n if (souls.length > maxGraphSize) {\n // Sort by oldest state timestamp and remove oldest entries\n const soulsByAge = souls\n .map(soul => {\n const states = graph[soul]._ && graph[soul]._[\">\"]\n const maxState = states ? Math.max(...Object.values(states)) : 0\n return {soul, maxState}\n })\n .sort((a, b) => a.maxState - b.maxState)\n const remove = soulsByAge.slice(0, souls.length - maxGraphSize)\n remove.forEach(({soul}) => {\n delete graph[soul]\n if (hasNode) hasNode.delete(soul)\n })\n }\n\n return {now: now, defer: defer, wait: wait, listeners: listeners}\n}\n\nexport default Ham\n", "import * as utils from \"./utils.js\"\n\n// ASCII character for group separator.\nconst group = String.fromCharCode(29)\n// ASCII character for record separator.\nconst record = String.fromCharCode(30)\n\nconst Radix = () => {\n const radix = (keys, value, tree) => {\n if (!tree) {\n if (!radix[group]) radix[group] = {}\n tree = radix[group]\n }\n if (!keys) return tree\n\n let i = 0\n let tmp = {}\n let key = keys[i]\n const max = keys.length - 1\n const noValue = typeof value === \"undefined\"\n // Find a matching value using the shortest string from keys.\n let found = tree[key]\n while (!found && i < max) {\n key += keys[++i]\n found = tree[key]\n }\n\n if (!found) {\n if (noValue) {\n // If not found from the provided keys try matching with an existing\n // key.\n const result = utils.obj.map(tree, (hasValue, hasKey) => {\n let j = 0\n let matchingKey = \"\"\n while (hasKey[j] === keys[j]) {\n matchingKey += hasKey[j++]\n }\n if (matchingKey) {\n // matchingKey has to be as long as the original keys when\n // reading.\n if (j <= max) return\n\n tmp[hasKey.slice(j)] = hasValue\n return hasValue\n }\n })\n if (!result) return\n\n return tmp\n }\n\n // Writing: find the EXISTING key with the longest shared prefix,\n // not just the first one with any overlap at all (obj.map stops at\n // the first non-undefined result, so a plain find here would settle\n // for whichever candidate happens to come first in Object.keys'\n // own iteration order). A radix tree's own invariant - no two\n // sibling keys share a prefix - only holds if every insertion\n // merges with its one true match; with many keys sharing this tree\n // at once (many concurrent writers batched together), a\n // coincidentally shorter, unrelated key can otherwise \"win\" over\n // the real, much longer match - silently misplacing the new key\n // under the wrong group, while its actual sibling is never touched\n // at all and stays wherever it already was, invisible to any read\n // that expects it inside this new group.\n let bestKey = null\n let bestMatch = \"\"\n for (const hasKey of Object.keys(tree)) {\n let j = 0\n let matchingKey = \"\"\n while (hasKey[j] === keys[j]) {\n matchingKey += hasKey[j++]\n }\n if (matchingKey.length > bestMatch.length) {\n bestKey = hasKey\n bestMatch = matchingKey\n }\n }\n\n if (bestKey) {\n const hasValue = tree[bestKey]\n const j = bestMatch.length\n let replace = {\n [bestKey.slice(j)]: hasValue,\n [keys.slice(j)]: {[record]: value},\n }\n tree[bestMatch] = {[group]: replace}\n delete tree[bestKey]\n } else {\n if (!tree[key]) tree[key] = {}\n tree[key][record] = value\n }\n } else if (i === max) {\n // If no value use the key provided to return a whole group or record.\n if (noValue) {\n // If an individual record isn't found then return the whole group.\n return typeof found[record] === \"undefined\"\n ? found[group]\n : found[record]\n }\n // Otherwise create a new record at the provided key for value.\n found[record] = value\n } else {\n // Found at a shorter key, try again.\n if (!found[group] && !noValue) found[group] = {}\n return radix(keys.slice(++i), value, found[group])\n }\n }\n return radix\n}\n\nRadix.map = function map(radix, cb, opt, pre) {\n if (!pre) pre = []\n var tree = radix[group] || radix\n var keys = Object.keys(tree).sort()\n var u\n\n for (let i = 0; i < keys.length; i++) {\n let key = keys[i]\n let found = tree[key]\n let tmp = found[record]\n if (typeof tmp !== \"undefined\") {\n tmp = cb(tmp, pre.join(\"\") + key, key, pre)\n if (typeof tmp !== \"undefined\") return tmp\n } else if (opt) {\n cb(u, pre.join(\"\"), key, pre)\n }\n if (found[group]) {\n pre.push(key)\n tmp = map(found[group], cb, opt, pre)\n if (typeof tmp !== \"undefined\") return tmp\n pre.pop()\n }\n }\n}\n\nexport default Radix\n", "import Radix from \"./radix.js\"\nimport * as utils from \"./utils.js\"\n\n// ASCII character for end of text\nconst etx = String.fromCharCode(3)\n// ASCII character for enquiry\nconst enq = String.fromCharCode(5)\n// ASCII character for unit separator\nconst unit = String.fromCharCode(31)\n\n// Radisk provides access to a radix tree that is stored in the provided\n// opt.store interface\nconst Radisk = opt => {\n var u\n\n // Multi-file cache for all parsed radix trees\n const cache = new Map()\n // File listing cache to avoid repeated directory scans\n let fileListCache = null\n let fileListCacheTime = 0\n const FILE_LIST_CACHE_TTL = 10000 // 10 seconds\n // Pending reads queue to avoid duplicate reads for the same key\n const pendingReads = new Map()\n\n // Memory monitoring and cleanup\n let lastMemoryCheck = 0\n const MEMORY_CHECK_INTERVAL = 30000 // Check every 30 seconds\n const HEAP_WARNING_THRESHOLD = 0.8 // Warn at 80% of max heap size\n const HEAP_CLEANUP_THRESHOLD = 0.9 // Clean cache at 90% of max heap size\n\n if (!opt) opt = {}\n if (!opt.log) opt.log = console.log\n if (!opt.batch) opt.batch = 100 // Balanced batch size for performance\n if (!opt.write) opt.write = 1 // Wait time before write in milliseconds\n if (!opt.size) opt.size = 1024 * 1024 // File size on disk, default 1MB\n if (!opt.memoryLimit) opt.memoryLimit = 500 // Memory limit in MB\n if (typeof opt.cache === \"undefined\") opt.cache = true // Used in tests\n\n if (!opt.store) {\n opt.log(\n \"Radisk needs `store` interface with `{get: fn, put: fn, list: fn}`\",\n )\n return\n }\n if (!opt.store.get) {\n opt.log(\"Radisk needs `store.get` interface with `(file, cb)`\")\n return\n }\n if (!opt.store.put) {\n opt.log(\"Radisk needs `store.put` interface with `(file, data, cb)`\")\n return\n }\n if (!opt.store.list) {\n opt.log(\"Radisk needs a streaming `store.list` interface with `(cb)`\")\n return\n }\n\n // Memory monitoring and cache cleanup\n const checkMemoryUsage = () => {\n if (typeof process === \"undefined\" || !process.memoryUsage) return\n\n const now = Date.now()\n if (now - lastMemoryCheck < MEMORY_CHECK_INTERVAL) return\n lastMemoryCheck = now\n\n const memUsage = process.memoryUsage()\n const heapUsed = memUsage.heapUsed\n const heapTotal = memUsage.heapTotal\n const maxHeapSize = opt.memoryLimit * 1024 * 1024\n const heapUsageRatio = heapUsed / maxHeapSize\n\n if (heapUsageRatio > HEAP_CLEANUP_THRESHOLD) {\n const cacheSize = cache.size\n console.log(\n `[RADISK-MEMORY] High memory usage: ${Math.round(heapUsageRatio * 100)}% of heap limit. Clearing ${cacheSize} cached files.`,\n )\n cache.clear()\n // Force garbage collection if available\n if (global.gc) {\n global.gc()\n }\n // Reset timer to avoid immediate re-check until GC has time to work\n lastMemoryCheck = now + MEMORY_CHECK_INTERVAL\n } else if (heapUsageRatio > HEAP_WARNING_THRESHOLD) {\n console.log(\n `[RADISK-MEMORY] Memory warning: ${Math.round(heapUsageRatio * 100)}% of heap limit used. Cache size: ${cache.size} files.`,\n )\n }\n }\n\n // Any and all storage adapters should:\n // 1. Because writing to disk takes time, we should batch data to disk.\n // This improves performance, and reduces potential disk corruption.\n // 2. If a batch exceeds a certain number of writes, we should immediately\n // write to disk when physically possible. This caps total performance,\n // but reduces potential loss.\n const radisk = (key, value, cb) => {\n key = \"\" + key\n\n // If no value is provided then the second parameter is the callback\n // function. Read value from memory or disk and call callback with it.\n if (typeof value === \"function\") {\n cb = value\n value = radisk.batch(key)\n if (typeof value !== \"undefined\") {\n return cb(u, value)\n }\n\n if (radisk.thrash.at) {\n value = radisk.thrash.at(key)\n if (typeof value !== \"undefined\") {\n return cb(u, value)\n }\n }\n\n if (pendingReads.has(key)) {\n pendingReads.get(key).push(cb)\n return\n }\n\n pendingReads.set(key, [cb])\n // If radisk.read genuinely hangs (fd leak, stuck I/O), recover\n // callbacks as a cache miss so callers can fall through to the wire path.\n // 30s is long enough to distinguish a hang from a slow-but-healthy read.\n const timeout = setTimeout(() => {\n const callbacks = pendingReads.get(key)\n if (!callbacks) return\n opt.log(`radisk read hang detected for key: ${key}`)\n pendingReads.delete(key)\n callbacks.forEach(callback => callback(null, null))\n }, 30000)\n return radisk.read(key, (err, result) => {\n clearTimeout(timeout)\n const callbacks = pendingReads.get(key) || []\n pendingReads.delete(key)\n callbacks.forEach(callback => callback(err, result))\n })\n }\n\n // Otherwise store the value provided.\n radisk.batch(key, value)\n // Check memory usage after writing to in-memory radix tree\n checkMemoryUsage()\n if (cb) {\n radisk.batch.acks.push(cb)\n }\n // Don't wait if we have batched too many.\n if (++radisk.batch.ed >= opt.batch) {\n return radisk.thrash()\n }\n\n // Otherwise wait for more updates before writing.\n clearTimeout(radisk.batch.timeout)\n radisk.batch.timeout = setTimeout(radisk.thrash, opt.write)\n }\n\n radisk.batch = Radix()\n radisk.batch.acks = []\n radisk.batch.ed = 0\n\n radisk.thrash = () => {\n if (radisk.thrash.ing) {\n return (radisk.thrash.more = true)\n }\n\n clearTimeout(radisk.batch.timeout)\n radisk.thrash.more = false\n radisk.thrash.ing = true\n var batch = (radisk.thrash.at = radisk.batch)\n radisk.batch = null\n radisk.batch = Radix()\n radisk.batch.acks = []\n radisk.batch.ed = 0\n radisk.save(batch, err => {\n if (err) opt.log(err)\n batch.acks.forEach(cb => cb(err))\n radisk.thrash.at = null\n radisk.thrash.ing = false\n if (radisk.thrash.more) radisk.thrash()\n })\n }\n\n // 1. Find the first radix item in memory\n // 2. Use that as the starting index in the directory of files\n // 3. Find the first file that is lexically larger than it\n // 4. Read the previous file into memory\n // 5. Scan through in memory radix for all values lexically less than limit\n // 6. Merge and write all of those to the in-memory file and back to disk\n radisk.save = (rad, cb) => {\n const save = {\n find: (tree, key) => {\n // This is false for any key until save.start is set to an initial key.\n if (key < save.start) return\n\n save.start = key\n // store.list's own streamed order isn't guaranteed to be sorted -\n // fs.readdir in particular makes no such promise, unlike\n // radisk.read's own file lookup, which already sorts before\n // searching. Collect the full list and sort it first, rather\n // than scanning the raw stream as it arrives, since save.lex's\n // own boundary search below only works correctly over genuinely\n // sorted input - fed an unsorted stream, it can match the wrong\n // file, or stop tracking new candidates the moment the stream\n // stops looking monotonic, silently losing track of files that\n // arrive afterward.\n const files = []\n opt.store.list(file => {\n if (file) {\n files.push(file)\n return\n }\n files.sort()\n save.lex(files)\n })\n return true\n },\n lex: files => {\n // save.start can be set to undefined by a previous call to\n // save.mix, so don't continue in this case.\n if (!save.start) return\n\n let candidate = null\n for (const file of files) {\n if (file > save.start) {\n // ! is used as the first file name as it's the first\n // printable character, so always matches as lexically less\n // than any node.\n save.mix(candidate || \"!\", save.start, file)\n return\n }\n candidate = file\n }\n save.mix(candidate || \"!\", save.start, u)\n },\n mix: (file, start, end) => {\n save.start = u\n // Use cache if available, otherwise parse from disk\n if (cache.has(file)) {\n const disk = cache.get(file)\n Radix.map(rad, (value, key) => {\n if (key < start) return\n\n if (end && end < key) {\n // Found where the next file segment starts - stop here (the\n // non-undefined return is what actually stops Radix.map's\n // own iteration). Without it, the scan kept going through\n // every remaining entry in the whole batch, each one\n // overwriting save.start in turn, so save.next's own resume\n // point ended up as the LAST key in the batch rather than\n // the very next one - silently skipping every entry in\n // between as \"already processed\" when none of them ever\n // were.\n save.start = key\n return true\n }\n\n disk(key, value)\n })\n radisk.write(file, disk, save.next)\n } else {\n radisk.parse(file, (err, disk) => {\n if (err) return cb(err)\n\n Radix.map(rad, (value, key) => {\n if (key < start) return\n\n if (end && end < key) {\n save.start = key\n return true\n }\n\n disk(key, value)\n })\n // Populate the cache with this merge synchronously, before the\n // async store.put below even starts - a write's own merged\n // result is always authoritative (it's this batch's actual\n // content), unlike a plain read's parse, which can't tell\n // whether it raced ahead of a write. Closes the window where a\n // concurrent read's own parse-from-disk (started before this\n // write, resolving after it) would otherwise be free to\n // populate the cache with stale, pre-write data - see\n // radisk.read's own matching change below.\n if (opt.cache) cache.set(file, disk)\n radisk.write(file, disk, save.next)\n })\n }\n },\n next: err => {\n if (err) return cb(err)\n\n if (save.start) return Radix.map(rad, save.find)\n\n cb(err)\n },\n }\n Radix.map(rad, save.find)\n }\n\n radisk.write = (file, rad, cb) => {\n // A split produces two independent opt.store.put calls - this file's\n // own (truncated) remainder below, and the recursive call for the\n // split-off sub-file. pending starts at 1 for this file's own write,\n // and is bumped to 2 the moment a split is decided, so cb only fires\n // once both halves are actually durable - calling it as soon as\n // whichever one finishes first (the previous behavior) let a caller\n // continue - including resolving the original put()'s own callback -\n // before the other half's data had actually been written.\n let pending = 1\n let firstErr = null\n const settle = err => {\n if (err && !firstErr) firstErr = err\n if (--pending > 0) return\n cb(firstErr)\n }\n const write = {\n text: \"\",\n limit: \"\",\n done: false,\n count: 0,\n halfKey: \"\", // soul ID at the ~opt.size/2 mark for a balanced split\n halfOffset: 0, // write.text.length before that entry\n each: (value, key, k, pre) => {\n // each is called for all keys, but stop adding to write.text when\n // write.slice is called, then the current contents of write.text\n // will be written to file.\n if (write.done) return\n\n write.count++\n value = typeof value === \"undefined\" ? \"\" : \"=\" + Radisk.encode(value)\n const enc =\n Radisk.encode(pre.length) + \"#\" + Radisk.encode(k) + value + \"\\n\"\n // Cannot split the file if only have one entry to write. Allow splitting\n // at depth > 0 only when k itself contains enq, meaning k is a full\n // \"soulId\\x05property\" key, not merely a property suffix of a shared\n // soul prefix. Use the full key (pre + k) to extract the soul boundary.\n const validBoundary =\n pre.length === 0 || (pre.length === 1 && k.includes(enq))\n\n // Record the first valid split boundary past the halfway mark so a\n // full overflow can split here instead of at the tail, keeping both\n // halves near opt.size/2 rather than leaving the file always full.\n if (\n !write.halfKey &&\n write.count > 1 &&\n write.text.length > opt.size / 2 &&\n validBoundary\n ) {\n const fullKey = pre.join(\"\") + k\n const end = fullKey.indexOf(enq)\n write.halfKey = end === -1 ? fullKey : fullKey.substring(0, end)\n write.halfOffset = write.text.length\n }\n\n if (\n write.count > 1 &&\n write.text.length + enc.length > opt.size &&\n validBoundary\n ) {\n const fullKey = pre.join(\"\") + k\n const end = fullKey.indexOf(enq)\n write.limit =\n write.halfKey || (end === -1 ? fullKey : fullKey.substring(0, end))\n // Cannot split if the key is the same as the current file name.\n if (write.limit !== file) {\n // Truncate to the balanced split point \u2014 text after halfOffset is\n // handled by the write.slice call below, which reads from rad.\n if (write.halfKey) {\n write.text = write.text.substring(0, write.halfOffset)\n }\n write.done = true\n write.sub = Radix()\n Radix.map(rad, write.slice)\n pending++\n radisk.write(write.limit, write.sub, settle)\n return\n }\n }\n\n write.text += enc\n },\n slice: (value, key) => {\n if (key < write.limit) return\n\n write.sub(key, value)\n },\n }\n Radix.map(rad, write.each, true)\n // There is always accumulated write.text to store once write.each has\n // finished.\n opt.store.put(file, write.text, err => {\n // If a split occurred the cached radix tree still contains entries that\n // were moved to the sub-file. Invalidate so the next save.mix re-reads\n // from disk rather than re-writing those entries back to this file.\n if (write.done) {\n cache.delete(file)\n fileListCache = null\n }\n settle(err)\n })\n }\n\n radisk.read = (key, cb) => {\n // Only the soul of the key is compared to filenames (see radisk.write).\n const end = key.indexOf(enq)\n const soul = end === -1 ? key : key.substring(0, end)\n\n // Binary search for largest filename <= soul in a sorted array.\n const findFile = files => {\n let lo = 0,\n hi = files.length - 1,\n result = null\n while (lo <= hi) {\n const mid = (lo + hi) >> 1\n if (files[mid] <= soul) {\n result = files[mid]\n lo = mid + 1\n } else {\n hi = mid - 1\n }\n }\n return result\n }\n\n const read = file => {\n if (!file) {\n cb(\"no file found\", u)\n return\n }\n if (opt.cache && cache.has(file)) {\n return cb(u, cache.get(file)(key))\n }\n radisk.parse(file, (err, disk) => {\n if (err) opt.log(err)\n // Never overwrite an existing cache entry from a plain read - it\n // can't tell whether it raced ahead of a concurrent write (started\n // before that write, but resolving after the write already\n // installed its own authoritative, freshly-merged entry - see\n // save.mix's own matching change). Only populate the cache when\n // nothing beat this read to it.\n if (disk && opt.cache && !cache.has(file)) {\n cache.set(file, disk)\n checkMemoryUsage()\n }\n cb(err, disk ? disk(key) : u)\n })\n }\n\n const now = Date.now()\n if (\n opt.cache &&\n fileListCache &&\n now - fileListCacheTime < FILE_LIST_CACHE_TTL\n ) {\n read(findFile(fileListCache, soul))\n } else {\n const files = []\n opt.store.list(file => {\n if (file) {\n files.push(file)\n return\n }\n files.sort()\n if (opt.cache) {\n fileListCache = files\n fileListCacheTime = now\n }\n read(findFile(files, soul))\n })\n }\n }\n\n // Let us start by assuming we are the only process that is\n // changing the directory or bucket. Not because we do not want\n // to be multi-process/machine, but because we want to experiment\n // with how much performance and scale we can get out of only one.\n // Then we can work on the harder problem of being multi-process.\n radisk.parse = (file, cb) => {\n const parse = {\n disk: Radix(),\n read: (err, data) => {\n if (err) return cb(err)\n\n if (!data) return cb(u, parse.disk)\n\n let pre = []\n let preString = \"\"\n // Work though data by splitting into 3 values. The first value says\n // if the second value is one of: the radix level for a key, the key\n // iteself, or a value. The third is the rest of the data to work with.\n let tmp = parse.split(data)\n while (tmp) {\n let key\n let value\n let i = tmp[1]\n tmp = parse.split(tmp[2]) || \"\"\n if (tmp[0] === \"#\") {\n key = tmp[1]\n // Optimize prefix building - avoid repeated joins\n if (i < pre.length) {\n pre.length = i\n }\n if (i <= pre.length) {\n pre[i] = key\n pre.length = i + 1\n }\n // Only rebuild preString when prefix changes\n preString = pre.join(\"\")\n }\n tmp = parse.split(tmp[2]) || \"\"\n if (tmp[0] === \"\\n\") continue\n\n if (tmp[0] === \"=\") value = tmp[1]\n if (typeof key !== \"undefined\" && typeof value !== \"undefined\") {\n parse.disk(preString, value)\n }\n tmp = parse.split(tmp[2])\n }\n cb(u, parse.disk)\n },\n split: data => {\n if (!data) return\n\n const i = data.indexOf(unit)\n if (i === -1) return\n\n const a = data.slice(0, i)\n let o = {}\n return [a, Radisk.decode(data.slice(i), o), data.slice(i + o.i)]\n },\n }\n opt.store.get(file, parse.read)\n }\n\n return radisk\n}\n\nRadisk.encode = data => {\n // A key should be passed in as a string to encode, a value can optionally be\n // an array of 2-3 items: [value, state] or [value, state, signature].\n let state = \"\"\n let sig = \"\"\n if (data instanceof Array && (data.length === 2 || data.length === 3)) {\n state = etx + data[1]\n if (data.length === 3 && data[2]) {\n sig = etx + data[2]\n }\n data = data[0]\n }\n\n if (typeof data === \"string\") {\n let i = 0\n let current = null\n let text = unit\n while ((current = data[i++])) {\n if (current === unit) text += unit\n }\n return text + '\"' + data + state + sig + unit\n }\n\n const rel = utils.rel.is(data)\n if (rel) return unit + \"#\" + rel + state + sig + unit\n\n if (utils.num.is(data)) return unit + \"+\" + (data || 0) + state + sig + unit\n\n if (data === true) return unit + \"+\" + state + sig + unit\n\n if (data === false) return unit + \"-\" + state + sig + unit\n\n if (data === null) return unit + \" \" + state + sig + unit\n}\n\nRadisk.decode = (data, obj) => {\n var i = -1\n var n = 0\n var current = null\n var previous = null\n var textStart = -1\n var textEnd = -1\n if (data[0] !== unit) return\n\n // Find a control character previous to the text we want, skipping\n // consecutive unit separator characters at the beginning of the data.\n while ((current = data[++i])) {\n if (previous) {\n if (textStart === -1) textStart = i\n if (current === unit) {\n if (--n <= 0) {\n textEnd = i\n break\n }\n }\n } else if (current === unit) {\n n++\n } else {\n previous = current || true\n }\n }\n\n const text =\n textStart !== -1 ? data.slice(textStart, textEnd !== -1 ? textEnd : i) : \"\"\n\n if (obj) obj.i = i + 1\n\n let parts = text.split(etx)\n let value = parts[0]\n let state = parts[1]\n let sig = parts[2]\n\n if (!state) {\n if (previous === '\"') return text\n\n if (previous === \"#\") return utils.rel.ify(text)\n\n if (previous === \"+\") {\n if (text.length === 0) return true\n\n return parseFloat(text)\n }\n\n if (previous === \"-\") return false\n\n if (previous === \" \") return null\n } else {\n state = parseFloat(state)\n // If state was found then return an array with [value, state] or [value, state, sig]\n if (sig) {\n if (previous === '\"') return [value, state, sig]\n\n if (previous === \"#\") return [utils.rel.ify(value), state, sig]\n\n if (previous === \"+\") {\n if (value.length === 0) return [true, state, sig]\n\n return [parseFloat(value), state, sig]\n }\n\n if (previous === \"-\") return [false, state, sig]\n\n if (previous === \" \") return [null, state, sig]\n } else {\n if (previous === '\"') return [value, state]\n\n if (previous === \"#\") return [utils.rel.ify(value), state]\n\n if (previous === \"+\") {\n if (value.length === 0) return [true, state]\n\n return [parseFloat(value), state]\n }\n\n if (previous === \"-\") return [false, state]\n\n if (previous === \" \") return [null, state]\n }\n }\n}\n\nexport default Radisk\n", "import Radisk from \"./radisk.js\"\nimport Radix from \"./radix.js\"\nimport * as utils from \"./utils.js\"\n\nconst isNode = typeof process !== \"undefined\" && process.versions?.node != null\nconst fs = isNode ? await import(/*webpackIgnore: true*/ \"node:fs\") : undefined\n\n// ASCII character for enquiry.\nconst enq = String.fromCharCode(5)\n// ASCII character for unit separator.\nconst unit = String.fromCharCode(31)\n// On-disk root node format.\nconst root = unit + \"+0\" + unit + \"#\" + unit + '\"root' + unit\n\nconst fileSystem = opt => {\n const dir = opt.file\n\n if (isNode) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir)\n if (!fs.existsSync(dir + \"/!\")) fs.writeFileSync(dir + \"/!\", root)\n\n return {\n get: (file, cb) => {\n fs.readFile(dir + \"/\" + file, (err, data) => {\n if (err) {\n if (err.code === \"ENOENT\") {\n cb()\n return\n }\n\n console.log(\"fs.readFile error:\", err)\n }\n if (data) data = data.toString()\n cb(err, data)\n })\n },\n put: (file, data, cb) => {\n // Don't put tmp files under dir so that they're not listed.\n var tmp = file + \".\" + utils.text.random(9) + \".tmp\"\n fs.writeFile(tmp, data, err => {\n if (err) {\n console.log(\"fs.writeFile error:\", err)\n cb(err)\n return\n }\n\n fs.rename(tmp, dir + \"/\" + file, cb)\n })\n },\n list: cb => {\n fs.readdir(dir, (err, files) => {\n if (err) {\n console.log(\"fs.readdir error:\", err)\n cb()\n return\n }\n\n files.forEach(cb)\n cb()\n })\n },\n }\n }\n\n if (opt.indexedDB) {\n let db\n const dbReady = new Promise((resolve, reject) => {\n const o = indexedDB.open(dir, 1)\n o.onupgradeneeded = event => {\n event.target.result.createObjectStore(dir)\n }\n o.onerror = event => {\n console.log(event)\n reject(event)\n }\n o.onsuccess = () => {\n db = o.result\n // Create the root node if it doesn't exist.\n if (db) {\n const tx = db.transaction([dir], \"readonly\")\n const req = tx.objectStore(dir).getKey(\"!\")\n req.onerror = () => {\n console.log(`error getting key ${dir}/!`)\n reject(req.error)\n }\n req.onsuccess = () => {\n if (!req.result) {\n const tx = db.transaction([dir], \"readwrite\")\n const req = tx.objectStore(dir).put(root, \"!\")\n req.onerror = () => {\n console.log(`error putting root on ${dir}/!`)\n reject(req.error)\n }\n req.onsuccess = () => {\n resolve()\n }\n } else {\n resolve()\n }\n }\n } else {\n console.log(\"error indexedDB not available\")\n reject(new Error(\"indexedDB not available\"))\n }\n }\n })\n\n return {\n get: (file, cb) => {\n const _get = (file, cb) => {\n const tx = db.transaction([dir], \"readonly\")\n const req = tx.objectStore(dir).get(file)\n req.onerror = () => {\n console.log(`error getting ${dir}/${file}`)\n cb(req.error)\n }\n req.onsuccess = () => {\n cb(null, req.result)\n }\n }\n\n dbReady\n .then(() => {\n _get(file, cb)\n })\n .catch(err => {\n cb(err)\n })\n },\n put: (file, data, cb) => {\n const _put = (file, data, cb) => {\n const tx = db.transaction([dir], \"readwrite\")\n const req = tx.objectStore(dir).put(data, file)\n req.onerror = () => {\n console.log(`error putting data on ${dir}/${file}`)\n cb(req.error)\n }\n req.onsuccess = () => {\n cb(null)\n }\n }\n\n dbReady\n .then(() => {\n _put(file, data, cb)\n })\n .catch(err => {\n cb(err)\n })\n },\n list: cb => {\n const _list = cb => {\n const tx = db.transaction([dir], \"readonly\")\n const req = tx.objectStore(dir).getAllKeys()\n req.onerror = () => {\n console.log(\"error getting keys for\", dir)\n cb()\n }\n req.onsuccess = () => {\n req.result.forEach(cb)\n cb()\n }\n }\n\n dbReady\n .then(() => {\n _list(cb)\n })\n .catch(err => {\n console.log(\"error indexedDB not available:\", err)\n cb()\n })\n },\n }\n }\n\n // No browser storage.\n return {\n get: (file, cb) => {\n cb(null, root)\n },\n put: (file, data, cb) => {\n cb(null)\n },\n list: cb => {\n cb(\"!\")\n cb()\n },\n }\n}\n\n// Store provides get and put methods that can access radisk.\nconst Store = opt => {\n if (!utils.obj.is(opt)) opt = {}\n opt.file = String(opt.file || \"radata\")\n if (!opt.store) opt.store = fileSystem(opt)\n const radisk = Radisk(opt)\n\n return {\n get: (lex, cb) => {\n if (!lex || !utils.obj.is(lex)) {\n cb(\"lex required\")\n return\n }\n if (!lex[\"#\"]) {\n cb(\"soul required in lex\")\n return\n }\n\n var soul = lex[\"#\"]\n var key = typeof lex[\".\"] === \"string\" ? lex[\".\"] : \"\"\n var node\n var signatures = {}\n const each = (value, k) => {\n if (k !== utils.userPublicKey && !utils.match(lex[\".\"], k)) return\n\n if (!node) node = {_: {\"#\": soul, \">\": {}}}\n node[k] = value[0]\n node._[\">\"][k] = value[1]\n // If signature is present, store it in _[\"s\"]\n if (value.length === 3 && value[2]) {\n signatures[value[1]] = value[2]\n }\n }\n\n // When doing a targeted property lookup, also fetch userPublicKey in\n // parallel so ham.js can verify signatures regardless of secure mode.\n // Full-soul scans (key=\"\") already surface it via Radix.map.\n const needsPubKey = key !== \"\" && key !== utils.userPublicKey\n let pending = needsPubKey ? 2 : 1\n let cbErr = null\n const finish = err => {\n if (err && !cbErr) cbErr = err\n if (--pending > 0) return\n const graph = {[soul]: node}\n if (node && Object.keys(signatures).length > 0) {\n node._[\"s\"] = signatures\n }\n cb(cbErr, graph)\n }\n\n radisk(soul + enq + key, (err, value) => {\n if (utils.obj.is(value)) {\n Radix.map(value, each)\n if (!node) each(value, key)\n } else if (value) {\n each(value, key)\n }\n finish(err)\n })\n\n if (needsPubKey) {\n radisk(soul + enq + utils.userPublicKey, (err, value) => {\n if (value && !utils.obj.is(value)) each(value, utils.userPublicKey)\n finish(err)\n })\n }\n },\n put: (graph, cb) => {\n if (!graph) {\n cb(\"graph required\")\n return\n }\n\n let count = 0\n let finished = false\n const ack = err => {\n count--\n if (finished) return\n\n if (err) {\n finished = true\n cb(err)\n return\n }\n\n if (count === 0) {\n finished = true\n cb(null)\n }\n }\n\n Object.keys(graph).forEach(soul => {\n var node = graph[soul]\n Object.keys(node).forEach(key => {\n if (key === \"_\") return\n\n count++\n let value = node[key]\n let state = node._[\">\"][key]\n let sig = node._[\"s\"] && node._[\"s\"][state]\n let data = sig ? [value, state, sig] : [value, state]\n radisk(soul + enq + key, data, ack)\n })\n })\n },\n }\n}\n\nexport {fileSystem}\nexport default Store\n", "import Dup from \"./dup.js\"\nimport Get from \"./get.js\"\nimport Ham from \"./ham.js\"\nimport Store from \"./store.js\"\nimport * as utils from \"./utils.js\"\n\nconst isNode = typeof process !== \"undefined\" && process.versions?.node != null\n\nconst wsModule = isNode ? await import(\"ws\") : undefined\nconst fs = isNode ? await import(/*webpackIgnore: true*/ \"node:fs\") : undefined\n\nif (typeof globalThis.WebSocket === \"undefined\") {\n globalThis.WebSocket = wsModule?.WebSocket\n}\n\n// Rate limiting with throttling\nconst createRateLimiter = isTestEnv => {\n const clients = new Map()\n const maxRequests = 1500 // requests per minute\n const windowMs = 60000 // 1 minute window\n const disconnectThreshold = 10 // Disconnect after 10 violations\n let cleanupInterval = null\n\n const cleanup = () => {\n const now = Date.now()\n for (const [clientId, data] of clients.entries()) {\n if (now - data.lastCleanup > windowMs) {\n data.requests = []\n data.lastCleanup = now\n }\n data.requests = data.requests.filter(time => now - time < windowMs)\n // Reset throttle counts periodically\n if (now - data.lastCleanup > windowMs * 10) {\n data.throttleCount = 0\n }\n }\n }\n\n if (!isTestEnv) {\n cleanupInterval = setInterval(cleanup, windowMs / 4)\n }\n\n return {\n getDelay: clientId => {\n const now = Date.now()\n const client = clients.get(clientId) || {\n requests: [],\n lastCleanup: now,\n throttleCount: 0,\n }\n\n // Filter old requests\n client.requests = client.requests.filter(time => now - time < windowMs)\n\n if (client.requests.length >= maxRequests) {\n // Calculate delay based on oldest request that will expire\n const oldestRequest = Math.min(...client.requests)\n const delay = windowMs - (now - oldestRequest)\n // Increment throttle count and update client data\n client.throttleCount = (client.throttleCount || 0) + 1\n clients.set(clientId, client)\n return Math.max(0, delay)\n }\n\n // No delay needed, track this request\n client.requests.push(now)\n clients.set(clientId, client)\n return 0\n },\n\n getRemainingRequests: clientId => {\n const client = clients.get(clientId)\n if (!client) return maxRequests\n\n const now = Date.now()\n const validRequests = client.requests.filter(\n time => now - time < windowMs,\n )\n return Math.max(0, maxRequests - validRequests.length)\n },\n\n getThrottleCount: clientId => {\n const client = clients.get(clientId)\n return client ? client.throttleCount || 0 : 0\n },\n\n shouldDisconnect: clientId => {\n const client = clients.get(clientId)\n if (!client) return false\n return client.throttleCount >= disconnectThreshold\n },\n\n destroy: () => {\n if (cleanupInterval) {\n clearInterval(cleanupInterval)\n cleanupInterval = null\n }\n clients.clear()\n },\n }\n}\n\n// Safe JSON parser with size limit\nconst safeJSONParse = (data, maxSize = 1024 * 1024) => {\n try {\n if (typeof data === \"string\" && data.length > maxSize) {\n throw new Error(\"Message too large\")\n }\n return {success: true, data: JSON.parse(data)}\n } catch (error) {\n return {success: false, error: error.message}\n }\n}\n\n// Message size validator\nconst validateMessage = (data, maxSize = 1024 * 1024) => {\n // 1MB default\n if (typeof data === \"string\" && data.length > maxSize) {\n return {valid: false, error: \"Message too large\"}\n }\n if (Buffer.isBuffer(data) && data.length > maxSize) {\n return {valid: false, error: \"Message too large\"}\n }\n return {valid: true}\n}\n\n// Connection manager to limit concurrent connections\nconst createConnectionManager = (maxConnections = 1000) => {\n const connections = new Set()\n\n return {\n add: ws => {\n if (connections.size >= maxConnections) {\n return false\n }\n connections.add(ws)\n\n // Clean up on close\n const originalClose = ws.close\n ws.close = (...args) => {\n connections.delete(ws)\n return originalClose.apply(ws, args)\n }\n\n return true\n },\n\n remove: ws => {\n connections.delete(ws)\n },\n\n count: () => connections.size,\n\n isFull: () => connections.size >= maxConnections,\n }\n}\n\n// Enhanced retry mechanism with exponential backoff\nconst createRetryHandler = (maxRetries = 5) => {\n let retryCount = 0\n\n return {\n shouldRetry: () => retryCount < maxRetries,\n getDelay: () => Math.min(1000 * Math.pow(2, retryCount), 30000), // Max 30s\n increment: () => retryCount++,\n reset: () => (retryCount = 0),\n }\n}\n\n// Wire starts a websocket client or server and returns get and put methods\n// for access to the wire spec and storage.\nconst Wire = opt => {\n const dup = Dup()\n const store = Store(opt)\n const graph = {}\n const queue = {}\n const listen = {}\n // Tracks souls that have had a complete full-node store fetch, so subsequent\n // full-node requests can read directly from the in-memory graph without a\n // redundant store round-trip. Kept in sync with graph eviction via Ham.mix.\n const hasNode = new Set()\n\n // Track references we want but don't have yet\n const pendingReferences = new Set()\n\n // Debounce client-side wire update checks: skip if the same lex was checked\n // recently. Keyed by \"soul\" or \"soul.property\".\n const recentChecks = new Map()\n const recentCheckTTL = 10000 // 10 seconds\n\n // Track pending timeouts that should start when message is sent\n const pendingTimeouts = new Map()\n\n // Track offline null-response timeouts so they can be cancelled if the WS\n // connects before they fire. Keyed by the same trackId as pendingTimeouts.\n const offlineTimeouts = new Map()\n\n // Helper to check if we have a soul in memory or storage\n const hasSoul = async soul => {\n if (graph[soul]) return true\n return new Promise(resolve => {\n store.get({\"#\": soul}, (err, data) => {\n resolve(!err && data && data[soul])\n })\n })\n }\n\n // Initialize rate limiting and connection management\n // Check if test environment (mock-socket usage)\n const isTestEnv = isNode && globalThis.WebSocket !== wsModule?.WebSocket\n const rateLimiter = createRateLimiter(isTestEnv)\n const connectionManager = createConnectionManager(opt.maxConnections || 1000)\n\n // User storage limiting \u2014 server-side only, requires opt.userLimit: true.\n const DEFAULT_STORAGE_LIMIT = 1 // 1 MB\n const defaultLimit =\n (typeof opt.defaultLimit === \"number\"\n ? opt.defaultLimit\n : DEFAULT_STORAGE_LIMIT) * 1048576\n const userStorage = new Map() // Map<pubkey, totalBytes>\n const userLimits = new Map() // Map<pubkey, maxBytes> converted from MB in .user_limit.json\n let saveStorageTimer = null\n\n const loadUserStorage = cb => {\n fs.readFile(`${opt.file}/../.user_storage.json`, \"utf8\", (err, raw) => {\n if (err) {\n if (cb) cb()\n return\n }\n\n try {\n const data = JSON.parse(raw)\n userStorage.clear()\n for (const [pub, total] of Object.entries(data)) {\n if (typeof total === \"number\") userStorage.set(pub, total)\n }\n } catch {\n // Invalid JSON \u2014 start with empty map.\n }\n if (cb) cb()\n })\n }\n\n const saveUserStorage = () => {\n if (saveStorageTimer) return\n\n const t = setTimeout(() => {\n saveStorageTimer = null\n const data = {}\n for (const [pub, total] of userStorage) {\n data[pub] = total\n }\n fs.writeFile(\n `${opt.file}/../.user_storage.json`,\n JSON.stringify(data),\n err => {\n if (err) console.warn(\"saveUserStorage error:\", err)\n },\n )\n }, 5000)\n if (t.unref) t.unref()\n saveStorageTimer = t\n }\n\n const loadUserLimits = cb => {\n fs.readFile(`${opt.file}/../.user_limit.json`, \"utf8\", (err, raw) => {\n if (err) {\n if (cb) cb()\n return\n }\n try {\n const data = JSON.parse(raw)\n userLimits.clear()\n for (const [pub, limit] of Object.entries(data)) {\n if (typeof limit === \"number\") userLimits.set(pub, limit * 1048576)\n // Non-numeric values ignored, falls back to defaultLimit.\n }\n } catch {\n // Invalid JSON \u2014 userLimits stays empty.\n }\n if (cb) cb()\n })\n }\n\n const formatBytes = bytes => {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(1)} MB`\n return `${(bytes / 1073741824).toFixed(1)} GB`\n }\n\n const logStorageSummary = () => {\n const userCount = userStorage.size\n const defLimitStr =\n defaultLimit === 0 ? \"unlisted users blocked\" : formatBytes(defaultLimit)\n console.log(\n `[HOLSTER] Per-user storage limits enabled (${userCount} user${userCount !== 1 ? \"s\" : \"\"}, default: ${defLimitStr})`,\n )\n const sorted = [...userStorage.entries()].sort(([, a], [, b]) => b - a)\n const logUser = pub => {\n const total = userStorage.get(pub) ?? 0\n const limit = userLimits.get(pub) ?? defaultLimit\n const limitStr = limit === 0 ? \"blocked\" : formatBytes(limit)\n console.log(\n ` ${pub.slice(0, 16)}... used: ${formatBytes(total)} / limit: ${limitStr}`,\n )\n }\n if (userCount <= 5) {\n sorted.forEach(([pub]) => logUser(pub))\n } else {\n console.log(\" Top 5 by storage used:\")\n sorted.slice(0, 5).forEach(([pub]) => logUser(pub))\n }\n console.log(\"Run npx holster-user-storage to view full keys and all users\")\n }\n\n // The check function is required because user data must provide a public key\n // so that it can be verified. The public key might verify the provided\n // signature but not actually match the user under which the data is being\n // stored. To avoid this, the current data on a soul needs to be checked to\n // make sure the stored public key matches the one provided with the update.\n // This must run before Ham.mix, which updates graph in place \u2014 checking\n // afterwards would compare the incoming update's public key against itself\n // instead of the previously stored one.\n const check = async (data, send, cb) => {\n const key = utils.userPublicKey\n\n for (const soul of Object.keys(data)) {\n const node = data[soul]\n // If the incoming update doesn't include a userPublicKey property at all,\n // allow it - the update is not trying to change the public key.\n if (node[key] === undefined) continue\n\n // A full-node lookup is required (rather than a targeted property\n // lookup) so that a soul which exists but has never had a public key\n // can be told apart from a soul that doesn't exist yet \u2014 both would\n // otherwise resolve to the same \"not found\" shape for this one key.\n const msg = await new Promise(res => {\n getWithCallback({\"#\": soul}, res, send, {put: true})\n })\n if (msg.err) {\n if (cb) cb(msg.err)\n return false\n }\n\n // If there is no current node then the data is ok to write without\n // matching public keys, as the provided soul also needs a rel on the\n // parent node which then also requires checking. Otherwise public keys\n // need to match for existing data.\n const existing = msg.put && msg.put[soul]\n if (\n !existing ||\n existing[key] === undefined ||\n existing[key] === node[key]\n ) {\n continue\n }\n\n // If a soul exists but does not have a public key, then one should not be\n // added because the node is not user data. The above check fails in this\n // case if a public key is provided. Note that this is only an error case\n // if called via the API, which is when a callback is provided here.\n // (The wire spec can fetch and put data on the wire without a signature\n // or public key and this can be ignored.)\n if (cb) {\n cb(`error in wire check public key does not match for soul: ${soul}`)\n }\n return false\n }\n\n return true\n }\n\n const get = (msg, send) => {\n const ack = Get(msg.get, graph)\n if (ack) {\n send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n put: ack,\n }),\n )\n } else {\n store.get(msg.get, (err, ack) => {\n send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n put: ack,\n err: err,\n }),\n )\n })\n }\n }\n\n const put = async (msg, send) => {\n // Capture old graph sizes before Ham.mix updates graph in place.\n const oldGraphBytes = {}\n if (opt.userLimit) {\n for (const [soul, node] of Object.entries(msg.put)) {\n if (node && node[utils.userPublicKey] && graph[soul]) {\n oldGraphBytes[soul] = JSON.stringify(graph[soul]).length\n }\n }\n }\n\n if (!(await check(msg.put, send))) return\n\n // Store updates returned from Ham.mix and defer updates if required.\n const update = await Ham.mix(\n msg.put,\n graph,\n hasNode,\n opt.secure,\n listen,\n opt.maxGraphSize,\n )\n if (Object.keys(update.now).length === 0) {\n // No updates to store, check deferred.\n if (Object.keys(update.defer).length !== 0) {\n setTimeout(\n () => put({put: update.defer, \"#\": msg[\"#\"]}, send),\n update.wait,\n )\n }\n return\n }\n\n const finish = err => {\n if (err) console.warn(\"store.put\", err)\n send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n err: err,\n }),\n )\n // Fire listeners after data is stored\n update.listeners.forEach(cb => cb())\n }\n\n if (!opt.userLimit) {\n store.put(update.now, finish)\n } else {\n const toStore = {}\n for (const [soul, node] of Object.entries(update.now)) {\n const pub = node[utils.userPublicKey]\n if (!pub) {\n toStore[soul] = node\n continue\n }\n const limit = userLimits.get(pub) ?? defaultLimit\n const current = userStorage.get(pub) ?? 0\n const oldBytes = oldGraphBytes[soul] ?? 0\n const newBytes = graph[soul] ? JSON.stringify(graph[soul]).length : 0\n const updated = Math.max(0, current - oldBytes + newBytes)\n // A write that doesn't grow this user's total usage (e.g. a\n // delete) is always let through, even past the limit - otherwise\n // a user already over quota could never delete anything to get\n // back under it. Only a write that both grows usage and pushes\n // the total past the limit is rejected.\n if (updated > current && updated > limit) continue\n toStore[soul] = node\n userStorage.set(pub, updated)\n saveUserStorage()\n }\n if (Object.keys(toStore).length > 0) {\n store.put(toStore, finish)\n } else {\n finish(null)\n }\n }\n\n if (Object.keys(update.defer).length !== 0) {\n setTimeout(\n () => put({put: update.defer, \"#\": msg[\"#\"]}, send),\n update.wait,\n )\n }\n }\n\n const getWithCallback = (lex, cb, send, _opt) => {\n if (!cb) return\n\n if (!utils.obj.is(_opt)) _opt = {}\n\n // For full-node requests on souls that have been fully fetched from store,\n // treat the graph as authoritative \u2014 skip the redundant store round-trip.\n const fast = _opt.fast || (!lex[\".\"] && hasNode.has(lex[\"#\"]))\n const ack = Get(lex, graph, fast)\n const track = utils.text.random(9)\n const request = JSON.stringify({\n \"#\": dup.track(track),\n get: lex,\n })\n\n if (ack) {\n if (!isNode) {\n // Client: send request on the wire to check for updates,\n // since it may have missed puts while disconnected.\n // Skip if the same lex was checked recently to avoid flooding.\n if (!lex[\".\"] || typeof lex[\".\"] === \"string\") {\n const checkKey = lex[\"#\"] + (lex[\".\"] ? \".\" + lex[\".\"] : \"\")\n const now = Date.now()\n const lastCheck = recentChecks.get(checkKey)\n if (!lastCheck || now - lastCheck > recentCheckTTL) {\n recentChecks.set(checkKey, now)\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n } else {\n // Don't skip checks for other types of lex queries.\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n }\n cb({put: ack})\n return\n }\n\n store.get(lex, (err, ack) => {\n if (ack) {\n // Populate in-memory graph from store data before sending the server\n // request, so stale server responses with older state are correctly\n // rejected by ham.mix.\n for (const [soul, node] of Object.entries(ack)) {\n if (!node) continue\n if (!graph[soul]) {\n graph[soul] = {...node}\n continue\n }\n // Merge properties absent from the current graph entry. Only add\n // missing keys \u2014 existing entries were set by ham.mix and represent\n // the authoritative merged state for those properties.\n for (const [key, value] of Object.entries(node)) {\n if (key === \"_\") continue\n if (typeof graph[soul][key] !== \"undefined\") continue\n graph[soul][key] = value\n if (\n node._ &&\n node._[\">\"] &&\n typeof node._[\">\"][key] !== \"undefined\"\n ) {\n const state = node._[\">\"][key]\n graph[soul]._[\">\"][key] = state\n if (node._[\"s\"] && node._[\"s\"][state]) {\n if (!graph[soul]._[\"s\"]) graph[soul]._[\"s\"] = {}\n graph[soul]._[\"s\"][state] = node._[\"s\"][state]\n }\n }\n }\n }\n // Full-node fetch: the graph is now complete for this soul.\n if (!lex[\".\"] && ack[lex[\"#\"]]) hasNode.add(lex[\"#\"])\n // Only serve from store if the requested property is present.\n const node = ack[lex[\"#\"]]\n const hasProperty =\n node &&\n Object.keys(node).some(\n key => key !== \"_\" && utils.match(lex[\".\"], key),\n )\n if (hasProperty) {\n // Public keys are immutable once written \u2014 never need a wire check.\n if (!isNode && lex[\".\"] !== utils.userPublicKey) {\n if (!lex[\".\"] || typeof lex[\".\"] === \"string\") {\n const checkKey = lex[\"#\"] + (lex[\".\"] ? \".\" + lex[\".\"] : \"\")\n const now = Date.now()\n const lastCheck = recentChecks.get(checkKey)\n if (!lastCheck || now - lastCheck > recentCheckTTL) {\n recentChecks.set(checkKey, now)\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n } else {\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n return\n }\n }\n }\n cb(err ? {put: ack, err: err} : {put: ack})\n return\n }\n }\n\n // Data wasn't found locally, log errors and call back after a timeout.\n if (err) console.log(err)\n\n // Put requests only need a local answer \u2014 skip the wire round-trip.\n if (_opt && _opt.put) {\n const id = lex[\"#\"]\n const ack = {[id]: null}\n if (typeof lex[\".\"] === \"string\") {\n ack[id] = {[lex[\".\"]]: null}\n }\n cb({put: ack})\n return\n }\n\n queue[track] = cb\n\n // Store lex to construct the null ack when the timeout fires\n pendingTimeouts.set(track, lex)\n\n // Ensure the requested soul is stored when the response arrives.\n pendingReferences.add(lex[\"#\"])\n\n const sendResult = send(request)\n if (sendResult && sendResult.err) {\n cb({err: sendResult.err})\n delete queue[track]\n pendingTimeouts.delete(track)\n return\n }\n })\n }\n\n const api = send => {\n return {\n get: (lex, cb, _opt) => {\n if (lex && typeof lex[\".\"] === \"number\") {\n lex = {...lex, \".\": String(lex[\".\"])}\n }\n // Mark requested soul as something we want to store\n if (lex && lex[\"#\"]) {\n pendingReferences.add(lex[\"#\"])\n }\n getWithCallback(lex, cb, send, _opt)\n },\n put: async (data, cb) => {\n // Deferred updates are only stored using wire spec, they're ignored\n // here using the api. This is ok because correct timestamps should be\n // used whereas wire spec needs to handle clock skew for updates\n // across the network.\n const oldGraphBytes = {}\n if (opt.userLimit) {\n for (const [soul, node] of Object.entries(data)) {\n if (node && node[utils.userPublicKey] && graph[soul]) {\n oldGraphBytes[soul] = JSON.stringify(graph[soul]).length\n }\n }\n }\n if (!(await check(data, send, cb))) {\n return\n }\n\n const update = await Ham.mix(\n data,\n graph,\n hasNode,\n opt.secure,\n listen,\n opt.maxGraphSize,\n )\n if (Object.keys(update.now).length === 0) {\n // No updates, still respond to callback.\n if (cb) cb(null)\n return\n }\n\n // Ham.mix has already merged this locally-authored update into\n // graph[soul], synchronously, before store.put below even starts\n // persisting it - mark it as fully known now rather than waiting\n // for a future disk fetch to do so, so a read landing in that\n // window doesn't get forced through a disk round-trip that could\n // itself race ahead of this same write and find nothing, even\n // though the correct answer was already sitting in memory.\n for (const soul of Object.keys(update.now)) {\n hasNode.add(soul)\n }\n\n if (opt.userLimit) {\n for (const [soul, node] of Object.entries(update.now)) {\n const pub = node[utils.userPublicKey]\n if (!pub) continue\n const limit = userLimits.get(pub) ?? defaultLimit\n const current = userStorage.get(pub) ?? 0\n const oldBytes = oldGraphBytes[soul] ?? 0\n const newBytes = graph[soul]\n ? JSON.stringify(graph[soul]).length\n : 0\n const updated = Math.max(0, current - oldBytes + newBytes)\n // A write that doesn't grow this user's total usage (e.g. a\n // delete) is always let through, even past the limit - otherwise\n // a user already over quota could never delete anything to get\n // back under it. Only a write that both grows usage and pushes\n // the total past the limit is rejected.\n if (updated > current && updated > limit) {\n if (cb) cb(\"storage limit exceeded\")\n return\n }\n\n userStorage.set(pub, updated)\n saveUserStorage()\n }\n }\n\n // Seed pendingReferences with any new references from API calls\n for (const [soul, node] of Object.entries(update.now)) {\n if (node && typeof node === \"object\") {\n for (const [key, value] of Object.entries(node)) {\n const soulId = utils.rel.is(value)\n if (soulId) {\n // Add referenced soul to pending list\n pendingReferences.add(soulId)\n }\n }\n }\n }\n\n store.put(update.now, err => {\n if (cb) cb(err)\n // Fire listeners after data is stored\n update.listeners.forEach(l => l())\n })\n\n // Always put data on the wire spec even if no local update needed\n const sendResult = send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n put: data,\n }),\n )\n // Handle queue overflow error.\n if (sendResult && sendResult.err) {\n if (cb) cb(sendResult.err)\n return\n }\n },\n on: (lex, cb, _get, _opt) => {\n if (lex && typeof lex[\".\"] === \"number\") {\n lex = {...lex, \".\": String(lex[\".\"])}\n }\n const soul = lex && lex[\"#\"]\n if (!soul || !cb) return\n\n if (listen[soul]) {\n listen[soul].push({\".\": lex[\".\"], cb: cb})\n } else {\n listen[soul] = [{\".\": lex[\".\"], cb: cb}]\n }\n if (_get) getWithCallback(lex, cb, send, _opt)\n },\n off: (lex, cb) => {\n const soul = lex && lex[\"#\"]\n if (!soul || !listen[soul]) return\n\n if (cb) {\n const found = listen[soul].find(l => l.cb === cb)\n if (found) {\n listen[soul].splice(listen[soul].indexOf(found), 1)\n }\n } else {\n // Remove all callbacks when none provided.\n delete listen[soul]\n }\n },\n }\n }\n\n if (isNode && (opt.wss || opt.server || opt.port != null)) {\n let wss = opt.wss\n // Node's websocket server provides clients as an array, whereas\n // mock-sockets provides clients as a function that returns an array.\n let clients = () => wss.clients()\n if (!wss) {\n const config = opt.server ? {server: opt.server} : {port: opt.port}\n wss = new wsModule.WebSocketServer(config)\n clients = () => wss.clients\n }\n\n const send = (data, isBinary) => {\n // Start timeout for this message now that it's being sent\n const msg = JSON.parse(data)\n const trackId = msg[\"#\"]\n if (trackId && pendingTimeouts.has(trackId)) {\n const lex = pendingTimeouts.get(trackId)\n pendingTimeouts.delete(trackId)\n\n setTimeout(\n () => {\n const cb = queue[trackId]\n if (cb) {\n const id = lex[\"#\"]\n const ack = {[id]: null}\n if (typeof lex[\".\"] === \"string\") {\n ack[id] = {[lex[\".\"]]: null}\n }\n cb({put: ack})\n delete queue[trackId]\n }\n },\n isTestEnv ? 100 : 10000,\n )\n }\n\n clients().forEach(client => {\n if (client && client.readyState === WebSocket.OPEN) {\n client.send(data, {binary: isBinary})\n } else {\n const retryHandler = client._retryHandler || createRetryHandler()\n client._retryHandler = retryHandler\n\n if (retryHandler.shouldRetry()) {\n const delay = retryHandler.getDelay()\n retryHandler.increment()\n\n setTimeout(() => {\n if (client && client.readyState === WebSocket.OPEN) {\n retryHandler.reset()\n client.send(data, {binary: isBinary})\n }\n }, delay)\n }\n }\n })\n }\n if (opt.userLimit) {\n loadUserStorage(() => loadUserLimits(() => logStorageSummary()))\n setInterval(loadUserLimits, 60000).unref()\n }\n\n wss.on(\"connection\", ws => {\n // Check connection limit\n if (!connectionManager.add(ws)) {\n console.log(\"Connection limit reached, rejecting connection\")\n ws.close(1013, \"Connection limit reached - try again later\")\n return\n }\n\n // Generate unique client ID for rate limiting\n const clientId = utils.text.random(9)\n console.log(`New WebSocket client connected: ${clientId}`)\n\n ws.on(\"error\", error => {\n console.log(\"WebSocket error:\", error)\n connectionManager.remove(ws)\n })\n\n ws.on(\"close\", () => {\n console.log(`WebSocket client disconnected: ${clientId}`)\n connectionManager.remove(ws)\n })\n\n ws.on(\"message\", (data, isBinary) => {\n // Validate message size\n const validation = validateMessage(data, opt.maxMessageSize)\n if (!validation.valid) {\n console.warn(`Invalid message: ${validation.error}`)\n ws.send(JSON.stringify({error: validation.error}))\n return\n }\n\n // Safe JSON parsing\n const parseResult = safeJSONParse(data, opt.maxMessageSize)\n if (!parseResult.success) {\n console.warn(`JSON parse error: ${parseResult.error}`)\n ws.send(JSON.stringify({error: \"Invalid JSON\"}))\n return\n }\n\n const msg = parseResult.data\n if (dup.check(msg[\"#\"])) return\n\n // Check rate limit and get delay\n const delay = rateLimiter.getDelay(clientId)\n // Log rate limiting activity and enforce stricter limits\n if (delay > 0) {\n const throttleCount = rateLimiter.getThrottleCount(clientId)\n console.log(\n `Client ${clientId}: rate limit exceeded, delay would be ${delay}ms, dropping message (throttle count: ${throttleCount})`,\n )\n // Check if we should disconnect the bad actor\n if (rateLimiter.shouldDisconnect(clientId)) {\n console.log(\n `Client ${clientId}: Disconnecting after ${throttleCount} throttle violations`,\n )\n ws.close(1008, \"Rate limit violations\")\n return\n }\n\n // Send throttle warning back to client instead of processing\n ws.send(\n JSON.stringify({\n \"#\": dup.track(utils.text.random(9)),\n \"@\": msg[\"#\"],\n err: `Rate limit exceeded. Slow down requests. Wait ${Math.ceil(delay / 1000)}s`,\n throttle: delay,\n }),\n )\n return\n }\n\n const processMessage = async () => {\n dup.track(msg[\"#\"])\n\n if (msg.get) get(msg, send)\n if (msg.put) await put(msg, send)\n send(data, isBinary)\n\n const id = msg[\"@\"]\n const cb = queue[id]\n if (cb) {\n delete msg[\"#\"]\n delete msg[\"@\"]\n cb(msg)\n\n delete queue[id]\n }\n }\n\n if (delay > 0) {\n // Throttle the client by delaying message processing\n setTimeout(processMessage, delay)\n } else {\n // Process immediately\n processMessage()\n }\n })\n })\n return api(send)\n }\n\n // Browser logic.\n const peers = []\n // Client-side throttling state\n let clientThrottled = false\n let throttleUntil = 0\n let messageQueue = []\n let offlinePuts = []\n let queueProcessor = null\n const maxQueueLength = opt.maxQueueLength || 10000\n\n const startResponseTimeout = (\n trackId,\n lex,\n delay = isTestEnv ? 100 : 10000,\n ) => {\n return setTimeout(() => {\n offlineTimeouts.delete(trackId)\n pendingTimeouts.delete(trackId)\n const cb = queue[trackId]\n // No-op on successful send as callback is removed from the queue.\n if (cb) {\n const id = lex[\"#\"]\n const ack = {[id]: null}\n if (typeof lex[\".\"] === \"string\") {\n ack[id] = {[lex[\".\"]]: null}\n }\n cb({put: ack})\n delete queue[trackId]\n }\n }, delay)\n }\n\n const processQueue = () => {\n if (messageQueue.length === 0) {\n queueProcessor = null\n return\n }\n\n const now = Date.now()\n if (clientThrottled && now < throttleUntil) {\n // Still throttled, schedule next queue check\n queueProcessor = setTimeout(\n processQueue,\n Math.min(1000, throttleUntil - now),\n )\n return\n }\n\n // Throttle period ended, resume processing\n if (clientThrottled && now >= throttleUntil) {\n console.log(`Throttle period ended, resuming queue processing`)\n clientThrottled = false\n throttleUntil = 0\n }\n\n // Process next message in queue\n const data = messageQueue[0]\n const sent = sendToPeers(data)\n\n const msg = JSON.parse(data)\n const trackId = msg[\"#\"]\n\n // Drop GET messages with no pending callback \u2014 these were already served\n // from local store so no caller is waiting for the wire response.\n const isStaleCheckMessage =\n !sent && msg.get && !pendingTimeouts.has(trackId)\n\n if (sent || isStaleCheckMessage) {\n messageQueue.shift()\n } else if (!sent && msg.put) {\n // Hold offline PUTs separately so they don't block GET messages behind\n // them. They'll be flushed back to the front of the queue on reconnect.\n messageQueue.shift()\n offlinePuts.push(data)\n }\n\n if (trackId && pendingTimeouts.has(trackId)) {\n const lex = pendingTimeouts.get(trackId)\n if (sent) {\n if (offlineTimeouts.has(trackId)) {\n clearTimeout(offlineTimeouts.get(trackId))\n offlineTimeouts.delete(trackId)\n }\n startResponseTimeout(trackId, lex)\n } else if (!offlineTimeouts.has(trackId)) {\n offlineTimeouts.set(trackId, startResponseTimeout(trackId, lex, 0))\n }\n }\n\n // Schedule processing of next message if queue not empty\n if (messageQueue.length > 0) {\n // Add delay between messages to respect rate limit\n queueProcessor = setTimeout(processQueue, 50)\n } else {\n queueProcessor = null\n }\n }\n\n const sendToPeers = data => {\n let sentToAtLeastOne = false\n peers.forEach(peer => {\n if (peer && peer.readyState === WebSocket.OPEN) {\n peer.send(data)\n sentToAtLeastOne = true\n } else {\n const retryHandler = peer._retryHandler || createRetryHandler()\n peer._retryHandler = retryHandler\n\n if (retryHandler.shouldRetry()) {\n const delay = retryHandler.getDelay()\n retryHandler.increment()\n\n setTimeout(() => {\n if (peer && peer.readyState === WebSocket.OPEN) {\n retryHandler.reset()\n peer.send(data)\n }\n }, delay)\n }\n }\n })\n return sentToAtLeastOne\n }\n\n const send = data => {\n if (messageQueue.length >= maxQueueLength) {\n return {\n err: `Message queue exceeded maximum length (${maxQueueLength}). Update query logic to request less data.`,\n queueLength: messageQueue.length,\n maxQueueLength: maxQueueLength,\n }\n }\n\n messageQueue.push(data)\n // Start queue processor if not already running\n if (!queueProcessor) {\n queueProcessor = setTimeout(processQueue, 50)\n }\n }\n if (!(opt.peers instanceof Array) || opt.peers.length === 0) {\n opt.peers = [`ws://localhost:${opt.port || 8765}`]\n }\n opt.peers.forEach(peer => {\n const start = () => {\n let ws = new WebSocket(peer)\n peers.push(ws)\n const retryHandler = createRetryHandler()\n\n ws.onclose = c => {\n if (peers.indexOf(ws) !== -1) {\n peers.splice(peers.indexOf(ws), 1)\n }\n ws = null\n\n if (retryHandler.shouldRetry()) {\n const delay = isTestEnv ? 50 : retryHandler.getDelay()\n retryHandler.increment()\n const t = setTimeout(start, delay)\n if (t.unref) t.unref()\n }\n }\n\n ws.onopen = () => {\n retryHandler.reset()\n if (offlinePuts.length > 0) {\n messageQueue = offlinePuts.concat(messageQueue)\n offlinePuts = []\n if (!queueProcessor) {\n queueProcessor = setTimeout(processQueue, 50)\n }\n }\n }\n\n ws.onerror = e => {\n console.log(e)\n }\n ws.onmessage = async m => {\n const msg = JSON.parse(m.data)\n if (dup.check(msg[\"#\"])) return\n\n // Handle throttle messages from server\n if (msg.throttle && msg.err) {\n console.log(`Server throttling: ${msg.err}`)\n clientThrottled = true\n throttleUntil = Date.now() + msg.throttle\n return\n }\n\n dup.track(msg[\"#\"])\n if (msg.get) get(msg, send)\n if (msg.put) {\n // Pre-pass: expand pendingReferences to include rels of every soul\n // that will be stored in this batch. This handles the case where a\n // server batch contains both a parent soul (e.g. day_soul with item\n // rels) and its child souls (item_souls), in any order \u2014 without the\n // pre-pass, a child soul that appears before its parent in the batch\n // would be missed because pendingReferences hasn't been updated yet.\n const hasSoulMap = new Map()\n for (const [soul, node] of Object.entries(msg.put)) {\n const known = await hasSoul(soul)\n hasSoulMap.set(soul, known)\n if (\n (!known && !pendingReferences.has(soul)) ||\n !node ||\n typeof node !== \"object\"\n )\n continue\n for (const [, value] of Object.entries(node)) {\n const soulId = utils.rel.is(value)\n if (soulId) pendingReferences.add(soulId)\n }\n }\n\n // Main pass: filter using cached hasSoul results and the now-complete\n // pendingReferences set.\n const filteredPut = {}\n const pendingToDelete = []\n for (const [soul, node] of Object.entries(msg.put)) {\n let shouldStore = hasSoulMap.get(soul)\n if (pendingReferences.has(soul)) {\n shouldStore = true\n // Don't delete from pendingReferences yet \u2014 concurrent onmessage\n // handlers for the same soul may have yielded at await hasSoul()\n // before this pass ran. Deleting here would cause those handlers\n // to see shouldStore=false and skip storing the soul's data.\n // Instead, defer the delete until after put() updates the graph,\n // so any concurrent handler can find the soul via hasSoul(graph).\n pendingToDelete.push(soul)\n }\n if (shouldStore) filteredPut[soul] = node\n }\n\n // Store filtered data if any\n if (Object.keys(filteredPut).length > 0) {\n // Create filtered message for Ham.mix with original message ID\n const filteredMsg = {put: filteredPut, \"#\": msg[\"#\"]}\n await put(filteredMsg, send)\n }\n\n // Safe to delete now \u2014 put() has run Ham.mix which updates graph\n // in-place, so hasSoul() will return true for these souls going\n // forward, making pendingReferences no longer needed for them.\n pendingToDelete.forEach(soul => pendingReferences.delete(soul))\n }\n\n const id = msg[\"@\"]\n const cb = queue[id]\n if (cb) {\n delete msg[\"#\"]\n delete msg[\"@\"]\n cb(msg)\n\n delete queue[id]\n }\n }\n }\n start()\n })\n\n return api(send)\n}\n\nexport default Wire\n", "import * as utils from \"./utils.js\"\nimport Wire from \"./wire.js\"\nimport SEA from \"./sea.js\"\nimport {userPublicKey, userSignature} from \"./utils.js\"\n\nconst User = (opt, wire) => {\n if (!wire) wire = Wire(opt)\n let pubs = []\n let creating = false\n let authing = false\n let retries = 0\n\n const auth = (username, password, newPassword, ack) => {\n const retry = username => {\n retries++\n auth(username, password, newPassword, ack)\n }\n const done = err => {\n pubs = []\n retries = 0\n authing = false\n ack(err)\n }\n const next = () => {\n if (pubs.length === 0) {\n done(\"Wrong username or password\")\n return\n }\n\n const pub = pubs.shift()\n wire.get({\"#\": pub, \".\": [\"auth\", \"pub\", \"epub\"]}, async msg => {\n if (msg.err) {\n done(`error getting ${pub}: ${msg.err}`)\n return\n }\n\n const data = msg.put && msg.put[pub]\n if (!data || !data.auth) return next()\n\n const auth = JSON.parse(data.auth)\n const work = await SEA.work(password, auth.salt)\n const dec = await SEA.decrypt(auth.enc, work)\n if (!dec) return next()\n\n user.is = {\n username: username,\n pub: data.pub,\n epub: data.epub,\n priv: dec.priv,\n epriv: dec.epriv,\n }\n if (newPassword !== \"\") {\n // Encrypt private key using new password and a new salt.\n const salt = utils.text.random(64)\n const work = await SEA.work(newPassword, salt)\n const enc = await SEA.encrypt(dec, work)\n // Only update the auth property with the new password encryption.\n const update = {\n auth: JSON.stringify({enc: enc, salt: salt}),\n }\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, user.is)\n const graph = utils.graph(pub, update, sig, data.pub, timestamp)\n wire.put(graph, err => {\n if (err) {\n done(`error putting ${update} on ${pub}: ${err}`)\n } else {\n done(null)\n }\n })\n return\n }\n\n done(null)\n })\n }\n\n if (retries > 9) {\n done(\"Wrong username or password\")\n return\n }\n\n const soul = \"~@\" + username\n wire.get({\"#\": soul}, async msg => {\n if (msg.err) {\n done(`error getting ${soul}: ${msg.err}`)\n return\n }\n\n const data = msg.put && msg.put[soul]\n if (!data) return retry(username)\n\n delete msg.put[soul]._\n // Usernames aren't guaranteed to be unique, so store the list and then\n // try each of them until one is successful with the given password.\n pubs = Object.keys(data)\n next()\n })\n }\n\n const user = {\n create: (username, password, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else console.log(err)\n }\n\n if (creating) {\n ack(\"User is already being created\")\n return\n }\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n creating = true\n\n const soul = \"~@\" + username\n wire.get({\"#\": soul}, async msg => {\n if (msg.err) {\n creating = false\n ack(`error getting ${soul}: ${msg.err}`)\n return\n }\n\n if (msg.put && msg.put[soul]) {\n creating = false\n ack(\"Username already exists\")\n return\n }\n\n const salt = utils.text.random(64)\n const work = await SEA.work(password, salt)\n const pair = await SEA.pair()\n const priv = {priv: pair.priv, epriv: pair.epriv}\n const enc = await SEA.encrypt(priv, work)\n const data = {\n username: username,\n pub: pair.pub,\n epub: pair.epub,\n auth: JSON.stringify({enc: enc, salt: salt}),\n }\n\n const pub = \"~\" + pair.pub\n // Sign the timestamp for new account\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, pair)\n const graph = utils.graph(pub, data, sig, pair.pub, timestamp)\n wire.put(graph, err => {\n creating = false\n if (err) {\n ack(`error putting ${data} on ${pub}: ${err}`)\n return\n }\n\n const rel = {[pub]: {\"#\": pub}}\n wire.put(utils.graph(soul, rel), err => {\n if (err) {\n ack(`error putting ${rel} on ${soul}: ${err}`)\n return\n }\n\n // Return null on success.\n if (cb) cb(null)\n })\n })\n })\n },\n auth: (username, password, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else if (err) console.log(err)\n }\n\n if (authing) {\n ack(\"User is already authenticating\")\n return\n }\n\n user.is = null\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n authing = true\n auth(username, password, \"\", ack)\n },\n change: (username, password, newPassword, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else if (err) console.log(err)\n }\n\n if (authing) {\n ack(\"User is already authenticating\")\n return\n }\n\n user.is = null\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n if (newPassword === \"\") {\n ack(\"Please provide a new password\")\n return\n }\n\n authing = true\n auth(username, password, newPassword, ack)\n },\n store: localStorage => {\n if (!user.is) {\n console.log(\"Please authenticate before calling store\")\n return\n }\n\n if (localStorage) {\n if (typeof globalThis.localStorage !== \"undefined\") {\n globalThis.localStorage.setItem(\"user.is\", JSON.stringify(user.is))\n }\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n globalThis.sessionStorage.removeItem(\"user.is\")\n }\n return\n }\n\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n globalThis.sessionStorage.setItem(\"user.is\", JSON.stringify(user.is))\n }\n if (typeof globalThis.localStorage !== \"undefined\") {\n globalThis.localStorage.removeItem(\"user.is\")\n }\n },\n recall: () => {\n if (typeof globalThis.localStorage !== \"undefined\") {\n const is = globalThis.localStorage.getItem(\"user.is\")\n if (is) {\n user.is = JSON.parse(is)\n return\n }\n }\n\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n const is = globalThis.sessionStorage.getItem(\"user.is\")\n if (is) {\n user.is = JSON.parse(is)\n }\n }\n },\n leave: () => {\n user.is = null\n if (typeof globalThis.localStorage !== \"undefined\") {\n globalThis.localStorage.removeItem(\"user.is\")\n }\n if (typeof globalThis.sessionStorage !== \"undefined\") {\n globalThis.sessionStorage.removeItem(\"user.is\")\n }\n },\n delete: (username, password, cb) => {\n const ack = err => {\n if (cb) cb(err)\n else console.log(err)\n }\n\n if (authing) {\n ack(\"User is already authenticating\")\n return\n }\n\n if (username === \"\") {\n ack(\"Please provide a username\")\n return\n }\n\n if (password === \"\") {\n ack(\"Please provide a password\")\n return\n }\n\n authing = true\n auth(username, password, \"\", async err => {\n if (err) {\n ack(err)\n return\n }\n\n const data = {username: null, pub: null, epub: null, auth: null}\n // Sign the timestamp for account deletion\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, user.is)\n const pub = \"~\" + user.is.pub\n const graph = utils.graph(pub, data, sig, user.is.pub, timestamp)\n wire.put(graph, err => {\n if (err) {\n ack(`error putting null on ${pub}: ${err}`)\n return\n }\n\n user.is = null\n // Return null on success. Note currently not updating ~@username,\n // not sure if allowing username re-user is a good idea anyway?\n if (cb) cb(null)\n })\n })\n },\n }\n return user\n}\n\nexport default User\n", "// Backs on(cb, _get, {nested: true}) - see holster.js. A plain on() only\n// resolves the node it's given; it never re-checks a child whose own\n// value is an object (which always has its own soul, since only scalars\n// live directly on a node) once that child's content changes in place -\n// nothing on the parent's own soul changes when that happens, so a\n// listener on the parent alone never sees it. get()'s own read-resolution\n// (holster.js) already recursively resolves every such child into plain\n// data for a one-time read - this doesn't repeat that; it adds a live\n// subscription for each child that resolution already exposed, so a\n// later change to it reaches the caller too.\n//\n// Pure and holster-internals-free: chain is a factory - () =>\n// user.get([host, \"shared\"]).next(\"domains\").next(code) - not a\n// pre-built chained object, since a fresh, independent instance is\n// needed per discovered child (reusing one chained object across\n// multiple .next() calls would push them onto the same path instead of\n// giving sibling paths).\nexport function attachNested(chain, cb, _get, _opt) {\n // Stripped before being used on any .on() call this function makes\n // itself (top-level or child) - otherwise a caller-provided {nested:\n // true} would re-trigger holster.js's own nested check on re-entry,\n // before the normal rel-resolution logic that actually finds the right\n // soul ever runs.\n const opt = {..._opt}\n delete opt.nested\n\n const childListeners = new Map() // key -> {api, handler}\n let latest = null\n\n const notify = () => cb(latest === null ? null : {...latest})\n\n const topLevelHandler = data => {\n if (data === null || typeof data !== \"object\") {\n latest = data\n notify()\n return\n }\n\n if (!latest || typeof latest !== \"object\") latest = {}\n for (const [key, value] of Object.entries(data)) {\n if (key === \"_\") continue\n latest[key] = value\n\n if (\n value !== null &&\n typeof value === \"object\" &&\n !childListeners.has(key)\n ) {\n const childApi = chain().next(key)\n const handler = childData => {\n if (childData === null) {\n delete latest[key]\n childListeners.delete(key)\n } else {\n latest[key] = childData\n }\n notify()\n }\n childListeners.set(key, {api: childApi, handler})\n // false, not true - the current value is already in data above,\n // so this only needs to watch for future changes, not trigger a\n // redundant immediate re-read.\n childApi.on(handler, false, opt)\n }\n }\n\n for (const key of [...childListeners.keys()]) {\n if (!(key in data)) {\n const {api: childApi, handler} = childListeners.get(key)\n childApi.off(handler)\n childListeners.delete(key)\n delete latest[key]\n }\n }\n\n notify()\n }\n\n const topLevelApi = chain()\n topLevelApi.on(topLevelHandler, _get, opt)\n\n return () => {\n topLevelApi.off(topLevelHandler)\n for (const {api: childApi, handler} of childListeners.values()) {\n childApi.off(handler)\n }\n childListeners.clear()\n }\n}\n", "import * as utils from \"./utils.js\"\nimport Wire from \"./wire.js\"\nimport User from \"./user.js\"\nimport SEA from \"./sea.js\"\nimport {attachNested} from \"./nested.js\"\n\nconst Holster = opt => {\n if (typeof opt === \"string\") opt = {peers: [opt]}\n else if (opt instanceof Array) opt = {peers: opt}\n else if (!utils.obj.is(opt)) opt = {}\n\n const wire = Wire(opt)\n const user = User(opt, wire)\n // Map callbacks since the user's callback is not passed to wire.on.\n const map = new Map()\n // Allow concurrent calls to the api by storing each context.\n const allctx = new Map()\n // Tracks on(..., {nested: true}) subscriptions, keyed by the caller's\n // own callback (the same reference off() will be called with) - see\n // attachNested in nested.js. The actual top-level/child listeners it\n // creates use their own, separate contexts, so off() just needs to\n // call the detach function this stores to tear the whole thing down.\n const nested = new Map()\n // Serializes concurrent creation of a missing rel for the same\n // soul+item, so only the first caller creates it and the rest reuse\n // its result rather than each minting a competing soul. Map<soul,\n // Map<item, promise resolving to the soul id>>.\n const pendingRel = new Map()\n\n const ok = data => {\n return (\n data === null ||\n data === true ||\n data === false ||\n typeof data === \"string\" ||\n utils.rel.is(data) ||\n utils.num.is(data)\n )\n }\n\n // check returns true if data is ok to add to a graph, an error string if\n // the data can't be converted, and the keys on the data object otherwise.\n const check = data => {\n if (ok(data)) return true\n\n if (utils.obj.is(data)) {\n const keys = []\n for (const [key, value] of Object.entries(data)) {\n if (key === \"_\") {\n return \"error underscore cannot be used as a property name\"\n }\n if (utils.obj.is(value) || ok(value)) {\n keys.push(key)\n continue\n }\n if (typeof value === \"undefined\") {\n return `error undefined ${key} cannot be converted to a graph`\n }\n const error = JSON.stringify({[key]: value})\n return `error ${error} cannot be converted to a graph`\n }\n if (keys.length !== 0) return keys\n }\n const error = JSON.stringify(data)\n return `error ${error} cannot be converted to a graph`\n }\n\n const api = ctxid => {\n const get = (lex, soul, ack, _opt) => {\n wire.get(\n utils.obj.put(lex, \"#\", soul),\n async msg => {\n if (msg.err) console.log(msg.err)\n if (msg.put && msg.put[soul]) {\n delete msg.put[soul]._\n delete msg.put[soul][utils.userPublicKey]\n delete msg.put[soul][utils.userSignature]\n // Resolve any rels on the node before returning to the user.\n await Promise.all(\n Object.keys(msg.put[soul]).map(async key => {\n const id = utils.rel.is(msg.put[soul][key])\n if (!id) return\n const attemptRead = async (retries = 0) => {\n const data = await new Promise(res => {\n const _ctxid = utils.text.random()\n const ctx = allctx.get(ctxid)\n allctx.set(_ctxid, {\n chain: [{item: null, soul: id}],\n user: ctx ? ctx.user : null,\n })\n api(_ctxid).next(null, res, _opt)\n })\n if (data !== null || retries >= 5) {\n return data\n }\n // Data not ready, retry after delay\n await new Promise(resolve => setTimeout(resolve, 50))\n return attemptRead(retries + 1)\n }\n msg.put[soul][key] = await attemptRead()\n }),\n )\n ack(msg.put[soul])\n } else {\n // No data callback.\n ack(null)\n }\n },\n _opt,\n )\n }\n\n const graph = async (soul, data, userctx, cb) => {\n if (userctx) {\n // Sign the timestamp\n const timestamp = Date.now()\n const sig = await SEA.signTimestamp(timestamp, userctx)\n return utils.graph(soul, data, sig, userctx.pub, timestamp)\n }\n\n if (opt.secure) {\n if (!cb) cb = console.log\n cb(`error putting data on ${soul}: user required in secure mode`)\n return null\n }\n\n return utils.graph(soul, data)\n }\n\n // done takes a context id and returns a new callback function so that the\n // callback is not overwritten by simultaneous requests.\n const done = ctxid => {\n return data => {\n const ctx = allctx.get(ctxid)\n if (ctx && typeof ctx.cb !== \"undefined\") {\n // Use a timeout so that the context can be removed before data is\n // returned to the callback (allows nested get calls).\n setTimeout(() => ctx.cb(data), 1)\n } else if (data) {\n console.log(\"error no callback for data\", data, \"ctx\", ctx)\n }\n // A context updated by \"on\" should only be removed by \"off\".\n if (ctx && !ctx.on) allctx.delete(ctxid)\n }\n }\n\n const watchForRel = (soul, item, ctx, i, request, cb, on = true) => {\n let timer = null\n const handler = () => {\n // Bail out if the context was removed by off().\n if (!allctx.has(ctxid)) {\n wire.off({\"#\": soul, \".\": item}, handler)\n if (timer) clearTimeout(timer)\n return\n }\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n const node = msg.put && msg.put[soul]\n const id = utils.rel.is(node && node[item])\n if (!id) {\n // If it's a plain value (not a rel) and this is a get, deliver it.\n // node._ guards against timeout null-acks which lack metadata.\n if (!on && node && node._ && typeof node[item] !== \"undefined\") {\n if (timer) clearTimeout(timer)\n wire.off({\"#\": soul, \".\": item}, handler)\n cb(node[item])\n }\n return\n }\n if (timer) clearTimeout(timer)\n wire.off({\"#\": soul, \".\": item}, handler)\n ctx.chain[i].soul = id\n allctx.set(ctxid, {...ctx})\n if (on) {\n api(ctxid).on(request.on, cb, request._get, request._opt)\n } else {\n api(ctxid).next(null, request.get, cb, request._opt)\n }\n },\n {...request._opt, secure: !!(ctx.user || opt.secure)},\n )\n }\n wire.on({\"#\": soul, \".\": item}, handler, false, request._opt)\n // Time out after the same total duration as the on() retry loop\n // (1+2+4+8+16 = 31s) so callers are not blocked forever if the node\n // genuinely doesn't exist.\n if (!on) {\n timer = setTimeout(() => {\n wire.off({\"#\": soul, \".\": item}, handler)\n if (cb) cb(null)\n }, 31000)\n }\n }\n\n // Creates a rel for item on soul, or reuses one already being created\n // by a concurrent caller for the same soul+item (see pendingRel above).\n // Calls cb(err, id) with a ready-to-display err, already prefixed where\n // needed - callers should pass it straight through, not wrap it again.\n const createRel = (soul, item, node, user, cb) => {\n let bySoul = pendingRel.get(soul)\n const pending = bySoul && bySoul.get(item)\n if (pending) {\n pending.then(\n id => cb(null, id),\n err => cb(err),\n )\n return\n }\n\n const id = utils.text.random()\n node[item] = utils.rel.ify(id)\n let settle, fail\n const promise = new Promise((res, rej) => {\n settle = res\n fail = rej\n })\n promise.catch(() => {})\n if (!bySoul) {\n bySoul = new Map()\n pendingRel.set(soul, bySoul)\n }\n bySoul.set(item, promise)\n const clear = () => {\n bySoul.delete(item)\n if (bySoul.size === 0) pendingRel.delete(soul)\n }\n\n ;(async () => {\n // graph() itself calls cb with an already-formatted message when it\n // fails (secure mode, no user) - pass cb straight through rather\n // than wrapping, so that message isn't prefixed a second time.\n const g = await graph(soul, node, user, cb)\n if (g === null) {\n clear()\n fail(new Error(\"secure mode\"))\n return\n }\n\n wire.put(g, err => {\n clear()\n if (err) {\n const message = `error putting ${item} on ${soul}: ${err}`\n fail(message)\n cb(message)\n return\n }\n\n settle(id)\n cb(null, id)\n })\n })()\n }\n\n const resolve = (request, cb) => {\n if (!request) {\n console.log(\"error resolve request parameter required\")\n return\n }\n\n const get = typeof request.get !== \"undefined\"\n const put = typeof request.put !== \"undefined\"\n const on = typeof request.on !== \"undefined\"\n const off = typeof request.off !== \"undefined\"\n\n let found = false\n const ctx = allctx.get(ctxid)\n if (!ctx) return {item: null, soul: null}\n for (var i = 1; i < ctx.chain.length; i++) {\n if (ctx.chain[i].soul !== null) continue\n\n found = true\n break\n }\n\n if (found) {\n // Found a soul that needs resolving, need the previous context\n // (ie the parent node) to find a soul relation for it.\n const {item, soul} = ctx.chain[i - 1]\n wire.get(\n {\"#\": soul, \".\": item},\n async msg => {\n if (msg.err) {\n console.log(`error getting ${item} on ${soul}: ${msg.err}`)\n if (cb) cb(null)\n return\n }\n\n let node = msg.put && msg.put[soul]\n if (node && typeof node[item] !== \"undefined\") {\n let id = utils.rel.is(node[item])\n if (id) {\n ctx.chain[i].soul = id\n allctx.set(ctxid, {...ctx})\n // Call api again using the updated context.\n if (get) {\n api(ctxid).next(null, request.get, cb, request._opt)\n } else if (put) {\n api(ctxid).put(request.put, cb)\n } else if (on) {\n api(ctxid).on(request.on, cb, request._get, request._opt)\n } else if (off) {\n api(ctxid).off(cb)\n }\n } else if (get) {\n // Request was not for a node, return property on current soul.\n cb(node[item])\n } else if (put) {\n // Request was chained before put, so rel doesn't exist yet.\n createRel(soul, item, node, ctx.user, (err, relId) => {\n if (err) {\n cb(err)\n return\n }\n\n ctx.chain[i].soul = relId\n api(ctxid).put(request.put, cb)\n })\n } else if (on) {\n // Item is not a rel yet \u2014 watch the parent soul for when it\n // becomes one, then retry chain resolution.\n watchForRel(soul, item, ctx, i, request, cb)\n if (request._get) cb(null)\n } else if (off) {\n // Allow stop listening to a node that doesn't exist.\n if (cb) cb(null)\n }\n } else if (put) {\n // Request was chained before put, so rel doesn't exist yet.\n createRel(soul, item, node || {}, ctx.user, (err, relId) => {\n if (err) {\n cb(err)\n return\n }\n\n ctx.chain[i].soul = relId\n api(ctxid).put(request.put, cb)\n })\n } else {\n if (on) {\n // Node doesn't exist yet \u2014 watch for it to appear.\n watchForRel(soul, item, ctx, i, request, cb)\n if (request._get) cb(null)\n } else if (get && node) {\n const sv = node._ && node._[\">\"]\n if (\n sv &&\n Object.keys(sv).length > 0 &&\n typeof sv[item] === \"undefined\"\n ) {\n // State vector has other properties but not this one \u2014 never written.\n if (cb) cb(null)\n } else {\n // Empty state vector or item is tracked \u2014 may arrive via push.\n watchForRel(soul, item, ctx, i, request, cb, false)\n }\n } else {\n // Soul doesn't exist or no get \u2014 return null.\n if (cb) cb(null)\n }\n }\n },\n {...request._opt, secure: !!(ctx.user || opt.secure)},\n )\n // Callback has been passed to next soul lookup or called above, so\n // return false as the calling code should not continue.\n return false\n }\n\n if (get && ctx.chain[ctx.chain.length - 1].item !== null) {\n // The context has been resolved but it does not include the requested\n // node, which requires one more lookup.\n ctx.chain.push({item: null, soul: null})\n api(ctxid).next(null, request.get, cb, request._opt)\n return false\n }\n\n // Return the last context, ie the soul required by the calling code.\n return ctx.chain[ctx.chain.length - 1]\n }\n\n return {\n get: (key, lex, cb, _opt) => {\n if (typeof lex === \"function\") {\n _opt = cb\n cb = lex\n lex = null\n }\n if (key === null || key === \"\" || key === \"_\") {\n console.log(\"error please provide a key\")\n if (cb) cb(null)\n return\n }\n\n // lex requires a callback as it's not included in the chain below.\n if (lex && typeof cb !== \"function\") {\n console.log(\"error lex requires a callback function\")\n return\n }\n\n // Top level keys are added to a root node so their values don't need\n // to be objects.\n ctxid = utils.text.random()\n allctx.set(ctxid, {chain: [{item: String(key), soul: \"root\"}], cb: cb})\n if (!cb) return api(ctxid)\n\n const _done = done(ctxid)\n // When there's a callback need to resolve the context first.\n const {soul} = resolve({get: lex, _opt: _opt}, _done)\n if (soul) get(lex, soul, _done, _opt)\n },\n next: (key, lex, cb, _opt) => {\n // ack needs to work the same as done, pass it the context id and then\n // return a new function for the actual callback.\n const ack = ctxid => {\n return data => {\n if (cb) {\n cb(data)\n } else {\n done(ctxid)(data)\n }\n }\n }\n if (typeof lex === \"function\") {\n _opt = cb\n cb = lex\n lex = null\n }\n if (!ctxid) {\n console.log(\"error please provide a key using get(key)\")\n if (cb) cb(null)\n return\n }\n\n const _ack = ack(ctxid)\n if (key === \"\" || key === \"_\") {\n _ack(null)\n return\n }\n\n // lex requires a callback as it's not included in the chain below.\n if (lex && typeof cb !== \"function\") {\n console.log(\"error lex requires a callback function\")\n return\n }\n\n const ctx = allctx.get(ctxid)\n // ctx already removed by another chained callback is ok?\n if (!ctx) return\n\n if (cb && typeof ctx.cb === \"undefined\") {\n // This (and ack) allows nested objects to set their own callbacks.\n ctx.cb = cb\n cb = null\n }\n\n // Push the key to the context as it needs a soul lookup.\n // (null is used to call the api with updated context)\n if (key !== null) ctx.chain.push({item: String(key), soul: null})\n if (!ctx.cb) return api(ctxid)\n\n // When there's a callback need to resolve the context first.\n const {soul} = resolve({get: lex, _opt: _opt}, _ack)\n if (soul) get(lex, soul, _ack, _opt)\n },\n put: (data, set, cb) => {\n if (typeof set === \"function\") {\n cb = set\n set = false\n }\n const ack = ctxid => {\n return data => {\n if (cb) {\n cb(data)\n } else {\n done(ctxid)(data)\n }\n }\n }\n if (!ctxid) {\n if (cb) cb(\"error please provide a key using get(key)\")\n return\n }\n\n const ctx = allctx.get(ctxid)\n // ctx already removed by another chained callback is ok?\n if (!ctx) return\n\n if (!ctx.cb && cb) {\n // This (and ack) allows nested objects to set their own callbacks.\n ctx.cb = cb\n cb = null\n }\n if (set) data = {[utils.text.random()]: data}\n\n const _ack = ack(ctxid)\n const result = check(data)\n if (typeof result === \"string\") {\n // All strings returned from check are errors, cannot continue.\n _ack(result)\n return\n }\n\n // Resolve the current context before putting data. (Note that set is\n // not passed to resolve because it's already been applied above.)\n const {item, soul} = resolve({put: data, _opt: {put: true}}, _ack)\n if (!soul) return\n\n if (result === true) {\n // When result is true data is a property to put on the current soul.\n // Need to check if item is a rel and also set the node to null. (This\n // applies for any update from a rel to a property, not just null.)\n wire.get(\n {\"#\": soul, \".\": item},\n async msg => {\n if (msg.err) {\n _ack(`error getting ${soul}: ${msg.err}`)\n return\n }\n\n let node = msg.put && msg.put[soul]\n const current = node && node[item]\n const id = utils.rel.is(current)\n if (!id) {\n // Not a rel, can just put the data.\n if (!node) node = {}\n node[item] = data\n const g = await graph(soul, node, ctx.user, _ack)\n if (g === null) return\n\n wire.put(g, _ack)\n return\n }\n\n wire.get({\"#\": id}, async msg => {\n if (msg.err) {\n _ack(`error getting ${id}: ${msg.err}`)\n return\n }\n\n if (!msg.put || !msg.put[id]) {\n _ack(`error ${id} not found`)\n return\n }\n\n // null each of the properties on the node before putting data.\n for (const key of Object.keys(msg.put[id])) {\n if (\n key === \"_\" ||\n key === utils.userPublicKey ||\n key === utils.userSignature\n ) {\n continue\n }\n\n const err = await new Promise(res => {\n const _ctxid = utils.text.random()\n const chain = [{item: key, soul: id}]\n allctx.set(_ctxid, {chain: chain, user: ctx.user})\n api(_ctxid).put(null, res)\n })\n if (err) {\n _ack(err)\n return\n }\n }\n if (!node) node = {}\n node[item] = data\n const g = await graph(soul, node, ctx.user, _ack)\n if (g === null) return\n\n wire.put(g, _ack)\n })\n },\n {secure: !!(ctx.user || opt.secure), put: true},\n )\n return\n }\n\n // Otherwise put the data using the keys returned in result.\n // Need to check if a rel has already been added on the current node.\n // Use attemptRead to retry if data hasn't propagated yet.\n const attemptRead = (retries = 0) => {\n wire.get(\n {\"#\": soul, \".\": item},\n async msg => {\n if (msg.err) {\n _ack(`error getting ${soul}.${item}: ${msg.err}`)\n return\n }\n\n let node = msg.put && msg.put[soul]\n const current = node && node[item]\n\n // If we didn't find the item but still have retries, retry\n if (!current && retries < 5) {\n await new Promise(r => setTimeout(r, 50))\n return attemptRead(retries + 1)\n }\n\n const id = utils.rel.is(current)\n if (!id) {\n // The current rel doesn't exist, so add it first.\n createRel(soul, item, node || {}, ctx.user, err => {\n if (err) {\n _ack(err)\n return\n }\n\n const _ctxid = utils.text.random()\n const chain = [{item: item, soul: soul}]\n // Pass on the previous ctx's callback and user flag here.\n allctx.set(_ctxid, {\n chain: chain,\n user: ctx.user,\n cb: ctx.cb,\n })\n api(_ctxid).put(data)\n })\n return\n }\n\n const update = []\n for (const key of result) {\n const err = await new Promise(res => {\n if (utils.obj.is(data[key]) && !utils.rel.is(data[key])) {\n // Use the current rel as the context for nested objects.\n const _ctxid = utils.text.random()\n const chain = [{item: key, soul: id}]\n allctx.set(_ctxid, {chain: chain, user: ctx.user})\n api(_ctxid).put(data[key], res)\n } else {\n // Group the rest of the updates for put below.\n update.push(key)\n res(null)\n }\n })\n if (err) {\n _ack(err, ctxid)\n return\n }\n }\n\n if (update.length === 0) {\n _ack(null)\n return\n }\n\n // Only write the primitive update keys. Rels created by the\n // recursive puts above are already in the in-memory graph.\n const updateNode = {}\n update.forEach(key => {\n updateNode[key] = data[key]\n })\n const g = await graph(id, updateNode, ctx.user, _ack)\n if (g === null) return\n\n wire.put(g, _ack)\n },\n {secure: !!(ctx.user || opt.secure), put: true},\n )\n }\n attemptRead()\n },\n on: (lex, cb, _get, _opt) => {\n if (typeof lex === \"function\") {\n _opt = _get\n _get = cb\n cb = lex\n lex = null\n }\n if (typeof cb !== \"function\") {\n console.log(\"error on() requires a callback function\")\n return\n }\n\n if (!ctxid) {\n console.log(\"error please provide a key using get(key)\")\n cb(null)\n return\n }\n\n // Resolve the current context before adding event listener.\n const {item, soul} = resolve({on: lex, _get: _get, _opt: _opt}, cb)\n if (!soul) return\n\n // Get the context to check if it has user info\n const ctx = allctx.get(ctxid)\n\n if (_opt && _opt.nested) {\n // attachNested calls this once for the top level and again for\n // every discovered child, each needing its own independent\n // context - a single shared _ctxid would accumulate .next()\n // calls onto the same path instead of giving sibling paths.\n const factory = () => {\n const _ctxid = utils.text.random()\n allctx.set(_ctxid, {\n chain: [{item: item, soul: soul}],\n user: ctx ? ctx.user : null,\n })\n return api(_ctxid)\n }\n nested.set(cb, attachNested(factory, cb, _get, _opt))\n return\n }\n\n // Flag that this context is set from on and shouldn't be removed.\n allctx.set(ctxid, {\n chain: [{item: item, soul: soul}],\n on: true,\n user: ctx ? ctx.user : null,\n })\n // Map the user's callback because it can also be passed to off,\n // so need a reference to it to compare them.\n // Shared retry state for this on() subscription.\n let retryCount = 0\n const maxRetries = 5\n const retryDelay = 1000 // Start with 1 second\n let retryTimer = null\n\n map.set(cb, () => {\n // Bail out if off() has already cleaned up this context \u2014 the mapped\n // callback can fire twice (once from wire.on and once from the _get\n // immediate-read path) and the second call after async context\n // cleanup would crash in resolve(). Matches the guard in watchForRel.\n if (!allctx.has(ctxid)) return\n // Cancel any pending retry \u2014 the persistent listener firing means we\n // have an update and should not call cb twice.\n clearTimeout(retryTimer)\n retryTimer = null\n // When listener fires, re-check if the item is now a rel.\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n const node = msg.put && msg.put[soul]\n const current = node && node[item]\n const id = utils.rel.is(current)\n if (id) {\n // It's a rel, read the related node. It might not be in the\n // graph yet when the listener fires, so we retry with delays.\n const attemptRead = async (retries = 0) => {\n const data = await new Promise(res => {\n const _ctxid = utils.text.random()\n allctx.set(_ctxid, {\n chain: [{item: null, soul: id}],\n user: ctx ? ctx.user : null,\n })\n api(_ctxid).next(\n null,\n res,\n retries === 0 ? utils.obj.put(_opt, \"fast\", true) : _opt,\n )\n })\n if (data !== null || retries >= 5) {\n retryCount = 0 // Reset retry counter on success\n cb(data)\n } else {\n // Data not ready, retry after delay\n await new Promise(resolve => setTimeout(resolve, 50))\n attemptRead(retries + 1)\n }\n }\n attemptRead()\n } else {\n // It's a direct property or null.\n const nodeExists = !!node\n\n if (nodeExists) {\n // Node exists \u2014 return the value and reset retry state.\n retryCount = 0\n cb(current !== undefined ? current : null)\n } else if (retryCount < maxRetries) {\n // No data yet \u2014 keep polling until we get a response or\n // exhaust retries. on() with _get can return null on a cache\n // miss and never fire again if the data doesn't change while\n // the listener is attached, so we must poll for initial load.\n const retry = () => {\n const delay = Math.min(\n retryDelay * Math.pow(2, retryCount),\n 30000,\n )\n retryCount++\n retryTimer = setTimeout(() => {\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n const retryNode = msg.put && msg.put[soul]\n if (retryNode) {\n retryCount = 0\n retryTimer = null\n const retryValue = retryNode[item]\n cb(retryValue !== undefined ? retryValue : null)\n } else if (retryCount < maxRetries) {\n retry()\n } else {\n retryTimer = null\n cb(null)\n }\n },\n {..._opt, secure: !!(ctx.user || opt.secure)},\n )\n }, delay)\n }\n retry()\n } else {\n cb(null)\n }\n }\n },\n {..._opt, secure: !!(ctx.user || opt.secure)},\n )\n })\n\n // Register listener immediately to avoid missing updates due to\n // queueing. Initially register the soul without _get, then update if\n // it's a rel.\n let initialLex\n if (lex) {\n initialLex = utils.obj.put(lex, \"#\", soul)\n // Normalize numeric property filters to strings for wire operations\n // Only convert if it's a number, not if it's a complex filter object\n if (initialLex[\".\"] != null && typeof initialLex[\".\"] === \"number\") {\n initialLex = {...initialLex, \".\": String(initialLex[\".\"])}\n }\n } else {\n initialLex = {\"#\": soul, \".\": item}\n }\n wire.on(initialLex, map.get(cb), false, _opt)\n\n // Check if item is a rel and update listener if needed.\n // This happens async but the listener is already registered above.\n wire.get(\n {\"#\": soul, \".\": item},\n msg => {\n if (msg.err) {\n console.log(`error getting ${soul}.${item}: ${msg.err}`)\n return\n }\n\n const current = msg.put && msg.put[soul] && msg.put[soul][item]\n const id = utils.rel.is(current)\n if (id) {\n // It's a rel, need to switch listener to the related node\n // First remove the initial listener\n wire.off(initialLex, map.get(cb))\n // Then add listener on the related node\n wire.on({\"#\": id, \".\": null}, map.get(cb), false, _opt)\n if (_get) map.get(cb)()\n } else if (_get) {\n // Not a rel, but _get was requested, so trigger callback.\n map.get(cb)()\n }\n },\n {..._opt, secure: !!(ctx.user || opt.secure)},\n )\n },\n off: cb => {\n if (!ctxid) {\n console.log(\"error please provide a key using get(key)\")\n if (cb) cb(null)\n return\n }\n\n if (nested.has(cb)) {\n nested.get(cb)()\n nested.delete(cb)\n return\n }\n\n // Resolve the current context before removing event listener.\n const {item, soul} = resolve({off: true}, cb)\n if (!soul) return\n\n // Remove listener immediately from the original soul to avoid a race\n // condition. The listener may be on a related soul if item is a rel,\n // but we remove from the original soul first since that's where it's\n //initially registered.\n wire.off({\"#\": soul}, map.get(cb))\n\n // Check if item is a rel and remove from the related node as well.\n wire.get({\"#\": soul, \".\": item}, msg => {\n if (msg.err) {\n // Even if get fails, we've already removed from original soul\n map.delete(cb)\n allctx.delete(ctxid)\n return\n }\n\n const current = msg.put && msg.put[soul] && msg.put[soul][item]\n const id = utils.rel.is(current)\n if (id) wire.off({\"#\": id}, map.get(cb))\n map.delete(cb)\n allctx.delete(ctxid)\n })\n },\n user: () => {\n if (!user.get) {\n // Return the combined Holster and User APIs.\n Object.assign(user, api())\n // Need to provide a user specific get() function to know if user\n // context should be checked.\n user.get = (keys, lex, cb, _opt) => {\n if (typeof lex === \"function\") {\n _opt = cb\n cb = lex\n lex = null\n }\n\n let pub = null\n let key = null\n if (user.is) pub = user.is.pub\n if (typeof keys === \"string\") {\n key = keys\n } else if (keys instanceof Array) {\n if (keys.length === 2) {\n pub = keys[0]\n key = keys[1]\n } else if (keys.length === 1) {\n key = keys[0]\n }\n }\n if (!pub) {\n console.log(\"error please log in or provide a public key\")\n if (cb) cb(null)\n return\n }\n\n if (key === null || key === \"\" || key === \"_\") {\n console.log(\"error please provide a key\")\n if (cb) cb(null)\n return\n }\n\n // lex requires a callback as it's not included in the chain below.\n if (lex && !cb) {\n console.log(\"error lex requires a callback function\")\n return\n }\n\n ctxid = utils.text.random()\n const chain = [{item: String(key), soul: \"~\" + pub}]\n allctx.set(ctxid, {chain: chain, user: user.is, cb: cb})\n if (!cb) return api(ctxid)\n\n // When there's a callback need to resolve the context first.\n const _done = done(ctxid)\n const {soul} = resolve({get: lex, _opt: _opt}, _done)\n if (soul) get(lex, soul, _done, _opt)\n }\n }\n return user\n },\n // Allow the wire spec to be used via holster.\n wire: wire,\n // Allow SEA functions to be used via holster.\n SEA: SEA,\n }\n }\n return api()\n}\n\nexport default Holster\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["num", "n", "parsed", "obj", "o", "match", "list", "cb", "keys", "i", "result", "key", "value", "map_soul", "soul", "rel", "userSignature", "userPublicKey", "graph", "data", "sig", "pub", "timestamp", "g", "lex", "prefix", "gt", "lt", "text", "length", "s", "c", "Dup", "dup", "id", "now", "dup_default", "Get", "lex", "graph", "fast", "soul", "node", "signatures", "key", "state", "userPublicKey", "pkState", "found", "match", "get_default", "data", "SeaArray", "enc", "start", "end", "buf", "byte", "_", "i", "charCode", "utf8String", "array_default", "SECURITY_LIMITS", "SafeBuffer", "props", "validateStringInput", "input", "encoding", "validateBufferSize", "size", "operation", "parseHexString", "hexString", "cleanHex", "bytes", "i", "hexByte", "encodeUtf8String", "str", "err", "encodeBinaryString", "charCode", "parseBase64String", "base64String", "cleanBase64", "decodedString", "processArrayLikeInput", "val", "arr", "array_default", "length", "fill", "buffer", "totalLength", "validatedBuffers", "item", "result", "offset", "obj", "string", "clean", "start", "end", "buffer_default", "isNode", "crypto", "subtle", "stringify", "data", "parse", "text", "random", "length", "array", "buffer_default", "jwk", "pub", "priv", "x", "y", "sha256", "hash", "aeskey", "key", "salt", "combined", "keyToJwk", "SEA", "cb", "ecdsa", "subtle", "keys", "pub", "ecdh", "pair", "data", "rand", "random", "ct", "aeskey", "aes", "stringify", "enc", "buffer_default", "dec", "parse", "signed", "key", "jwk", "msg", "k", "userPublicKey", "userSignature", "hash", "sha256", "sig", "alg", "verified", "check", "timestamp", "timestampStr", "signature", "publicKey", "isValid", "err", "salt", "work", "to", "from", "pubKey", "priv", "derived", "derivedBits", "derivedKey", "sea_default", "MAX_GRAPH_SIZE", "Ham", "state", "currentState", "value", "currentValue", "signed", "change", "graph", "hasNode", "secure", "listen", "maxGraphSize", "machine", "now", "defer", "listeners", "validProperties", "validTimestamps", "wait", "soul", "node", "updated", "alias", "nodeWait", "verify", "pub", "userPublicKey", "signedTimestamps", "signedProperties", "incomingTimestamps", "key", "sig", "asNumber", "propsForTimestamp", "ts", "prop", "sea_default", "rel", "skew", "isSigned", "l", "match", "souls", "states", "maxState", "a", "b", "ham_default", "group", "record", "Radix", "radix", "keys", "value", "tree", "i", "tmp", "key", "max", "noValue", "found", "obj", "hasValue", "hasKey", "j", "matchingKey", "bestKey", "bestMatch", "replace", "map", "cb", "opt", "pre", "u", "radix_default", "etx", "enq", "unit", "Radisk", "opt", "u", "cache", "fileListCache", "fileListCacheTime", "FILE_LIST_CACHE_TTL", "pendingReads", "lastMemoryCheck", "MEMORY_CHECK_INTERVAL", "HEAP_WARNING_THRESHOLD", "HEAP_CLEANUP_THRESHOLD", "checkMemoryUsage", "now", "memUsage", "heapUsed", "heapTotal", "maxHeapSize", "heapUsageRatio", "cacheSize", "radisk", "key", "value", "cb", "timeout", "callbacks", "callback", "err", "result", "radix_default", "batch", "rad", "save", "tree", "files", "file", "candidate", "start", "end", "disk", "pending", "firstErr", "settle", "write", "k", "pre", "enc", "validBoundary", "fullKey", "soul", "findFile", "lo", "hi", "mid", "read", "parse", "data", "preString", "tmp", "i", "a", "o", "state", "sig", "current", "text", "rel", "num", "obj", "previous", "textStart", "textEnd", "parts", "radisk_default", "isNode", "fs", "enq", "unit", "root", "fileSystem", "opt", "dir", "file", "cb", "err", "data", "tmp", "text", "files", "db", "dbReady", "resolve", "reject", "o", "event", "req", "_get", "_put", "_list", "Store", "obj", "radisk", "radisk_default", "lex", "soul", "key", "node", "signatures", "each", "value", "k", "userPublicKey", "match", "needsPubKey", "pending", "cbErr", "finish", "graph", "radix_default", "count", "finished", "ack", "state", "sig", "store_default", "Store", "isNode", "wsModule", "fs", "createRateLimiter", "isTestEnv", "clients", "maxRequests", "windowMs", "disconnectThreshold", "cleanupInterval", "now", "clientId", "data", "time", "client", "oldestRequest", "delay", "validRequests", "safeJSONParse", "maxSize", "error", "validateMessage", "createConnectionManager", "maxConnections", "connections", "ws", "originalClose", "args", "createRetryHandler", "maxRetries", "retryCount", "Wire", "opt", "dup", "dup_default", "store", "store_default", "graph", "queue", "listen", "hasNode", "pendingReferences", "recentChecks", "recentCheckTTL", "pendingTimeouts", "offlineTimeouts", "hasSoul", "soul", "resolve", "err", "rateLimiter", "connectionManager", "defaultLimit", "userStorage", "userLimits", "saveStorageTimer", "loadUserStorage", "cb", "raw", "pub", "total", "saveUserStorage", "t", "loadUserLimits", "limit", "formatBytes", "bytes", "logStorageSummary", "userCount", "defLimitStr", "sorted", "a", "b", "logUser", "limitStr", "check", "send", "key", "userPublicKey", "node", "msg", "res", "getWithCallback", "existing", "get", "ack", "get_default", "text", "put", "oldGraphBytes", "update", "ham_default", "finish", "toStore", "current", "oldBytes", "newBytes", "updated", "lex", "_opt", "obj", "fast", "track", "request", "checkKey", "lastCheck", "sendResult", "value", "state", "match", "id", "api", "soulId", "rel", "l", "_get", "found", "wss", "config", "isBinary", "trackId", "retryHandler", "validation", "parseResult", "throttleCount", "processMessage", "peers", "clientThrottled", "throttleUntil", "messageQueue", "offlinePuts", "queueProcessor", "maxQueueLength", "startResponseTimeout", "processQueue", "sent", "sendToPeers", "isStaleCheckMessage", "sentToAtLeastOne", "peer", "start", "c", "e", "m", "hasSoulMap", "known", "filteredPut", "pendingToDelete", "shouldStore", "filteredMsg", "wire_default", "User", "opt", "wire", "wire_default", "pubs", "creating", "authing", "retries", "auth", "username", "password", "newPassword", "ack", "retry", "done", "err", "next", "pub", "msg", "data", "work", "sea_default", "dec", "user", "salt", "text", "enc", "update", "timestamp", "sig", "graph", "soul", "cb", "pair", "priv", "rel", "localStorage", "is", "user_default", "attachNested", "chain", "cb", "_get", "_opt", "opt", "childListeners", "latest", "notify", "topLevelHandler", "data", "key", "value", "childApi", "handler", "childData", "topLevelApi", "Holster", "opt", "obj", "wire", "wire_default", "user", "user_default", "map", "allctx", "nested", "pendingRel", "ok", "data", "rel", "num", "check", "keys", "key", "value", "api", "ctxid", "get", "lex", "soul", "ack", "_opt", "msg", "userPublicKey", "userSignature", "id", "attemptRead", "retries", "res", "_ctxid", "text", "ctx", "resolve", "graph", "userctx", "cb", "timestamp", "sig", "sea_default", "done", "watchForRel", "item", "i", "request", "on", "timer", "handler", "node", "createRel", "bySoul", "pending", "err", "settle", "fail", "promise", "rej", "clear", "g", "message", "put", "off", "found", "relId", "sv", "_done", "_ack", "set", "result", "current", "chain", "r", "update", "updateNode", "_get", "factory", "attachNested", "retryCount", "maxRetries", "retryDelay", "retryTimer", "retry", "delay", "retryNode", "retryValue", "initialLex", "pub", "holster_default"]
|
|
7
7
|
}
|