{"_id":"@darksoil-studio/holochain-utils","name":"@darksoil-studio/holochain-utils","dist-tags":{"latest":"0.500.0"},"versions":{"0.500.0":{"name":"@darksoil-studio/holochain-utils","version":"0.500.0","description":"Common utilities to build Holochain web applications","author":{"name":"guillem.cordoba@gmail.com"},"main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","repository":{"type":"git","url":"git+https://github.com/darksoil-studio/holochain-utils.git"},"exports":{".":"./dist/index.js","./dist/*":"./dist/*"},"dependencies":{"@holochain/client":"^0.19.0","@msgpack/msgpack":"^2.8.0","blakejs":"^1.2.1","emittery":"^1.0.1","js-base64":"^3.7.7","lodash-es":"^4.17.21","sort-keys":"^5.0.0"},"devDependencies":{"@types/lodash-es":"^4.17.6","concurrently":"^7.0.0","rimraf":"^3.0.2","typescript":"^4.4.3","vite":"^4.1.1","vitest":"^1.4.0"},"publishConfig":{"access":"public"},"type":"module","scripts":{"build":"pnpm lint && tsc --incremental","build:watch":"tsc --watch --preserveWatchOutput","lint":"eslint src","test":"vitest run"},"_id":"@darksoil-studio/holochain-utils@0.500.0","bugs":{"url":"https://github.com/darksoil-studio/holochain-utils/issues"},"homepage":"https://github.com/darksoil-studio/holochain-utils#readme","_integrity":"sha512-E966Km27pimvxpSfpcCG8rjt+qBYTRJOhxe7LcJ4aS0HJuDQqb+m1VD/woDy6BPQ1UTEziYiw/ocnQ1YW4fgVA==","_resolved":"/tmp/881c2ee8f4beb7b1b8fc36a4f2c3be88/darksoil-studio-holochain-utils-0.500.0.tgz","_from":"file:darksoil-studio-holochain-utils-0.500.0.tgz","_nodeVersion":"20.19.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-E966Km27pimvxpSfpcCG8rjt+qBYTRJOhxe7LcJ4aS0HJuDQqb+m1VD/woDy6BPQ1UTEziYiw/ocnQ1YW4fgVA==","shasum":"3f72792455a13cc9be6e065c4c44c0ba68e2a1b9","tarball":"https://registry.npmjs.org/@darksoil-studio/holochain-utils/-/holochain-utils-0.500.0.tgz","fileCount":75,"unpackedSize":222004,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICGCzeoF4YS7Qz4rcF0LBlg4AzEyNuSARIdn3hEi+03lAiEAkWLBPwnk4Kpzdep5+QOjIu4kkdgQInRzCxr2EmoUI94="}]},"_npmUser":{"name":"guillem.cordoba","email":"guillem.cordoba@gmail.com"},"directories":{},"maintainers":[{"name":"guillem.cordoba","email":"guillem.cordoba@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/holochain-utils_0.500.0_1745401987331_0.4139033431664949"},"_hasShrinkwrap":false}},"time":{"created":"2025-04-23T09:53:07.239Z","0.500.0":"2025-04-23T09:53:07.474Z","modified":"2025-04-23T09:53:07.777Z"},"maintainers":[{"name":"guillem.cordoba","email":"guillem.cordoba@gmail.com"}],"description":"Common utilities to build Holochain web applications","homepage":"https://github.com/darksoil-studio/holochain-utils#readme","repository":{"type":"git","url":"git+https://github.com/darksoil-studio/holochain-utils.git"},"author":{"name":"guillem.cordoba@gmail.com"},"bugs":{"url":"https://github.com/darksoil-studio/holochain-utils/issues"},"readme":"# @darksoil-studio/holochain-utils\n\nUtilities to build Holochain web applications.\n\n## HoloHashMap \n\nMap of `HoloHash` to any JS object. \n\nWe can't really use well normal JS objects to index by holo hashes because we lose the ability to compare hashes together. Namely, in JS `console.log(new Uint8Array([1]) == new Uint8Array([1]))` prints `false`.\n\n```ts\nimport { AgentPubKey } from '@holochain/client';\nimport { HoloHashMap } from '@darksoil-studio/holochain-utils';\n\n// Imagine we have out public key\nconst myAgentPubKey = appInfo.cell_info[0].cell_id[1];\n\nconst map = new HoloHashMap<AgentPubKey, number>();\n\n// We can add entries to the dictionary\nmap.set(myAgentPubKey, 1);\n\n// Get the value for an entry\nconsole.log(map.get(myAgentPubKey));                // Will print `1`\n\n// Check if the key exists\nconsole.log(map.has(myAgentPubKey));                // Will print `true`\n\n// Get iterators for the entries\n\nconsole.log(Array.from(map.keys()));                // Will print an array with MYAGENTPUBKEY as the only member\nconsole.log(Array.from(map.values()));              // Will print `[1]`\nconsole.log(Array.from(map.entries()));             // Will print an array with `[MYAGENTPUBKEY, 1]` as the only member\n\nmap.delete(myAgentPubKey);                          // Will delete this member\n```\n\nSome variants exist for this type:\n\n- `EntryHashMap`\n- `ActionHashMap`\n- `AgentPubKeyMap`\n- `DnaHashMap`\n\n### MemoHoloHashMap\n\nThis is an special kind of map, where there is no `set` function, only `get`. \n\nInstead, a callback function is passed as the constructor. Then, whenever `get` is called, if it's the first time that the given hash is requested, it will call the callback and initialize the value of the hash with its result. If that hash was already initialized, it will just return that value.\n\n```ts\nimport { AgentPubKey, fakeAgentPubKey } from '@holochain/client';\nimport { MemoHoloHashMap } from '@darksoil-studio/holochain-utils';\n\nconst pubKey = fakeAgentPubKey();\n\n// Imagine we want to fetch the profile of the agent whenever an agent public key is requested\nconst memoMap = new MemoHoloHashMap((agent: AgentPubKey) => callZome('get_profile', agent));\n\nconsole.log(memoMap.get(pubKey)); // Will print a pending promise\n\n// After the request has finished...\nawait memoMap.get(pubKey);\n\nconsole.log(memoMap.get(pubKey)); // Will print a completed promise with the value\n```\n\n## EntryRecord\n\nUtility to type a single `Record` and extract useful information from them.\n\n```ts\nimport { Record } from '@holochain/client';\nimport { EntryRecord } from '@darksoil-studio/holochain-utils';\n\n// Imagine a zome function that returns a record,\n// but we know its entry type\nconst record: Record = await callZome(...);             \n\n// Then we can type it\nconst profileRecord = new EntryRecord<Profile>(record); \n\n// Access its entry easily\nconst profile: Profile = profileRecord.entry;           \n\n// Access its action easily, timestamp will be in milliseconds\nconst action: Action = profileRecord.action;            \n\n// Access its entry hash easily\nconst entryHash: EntryHash = profileRecord.entryHash;   \n\n// Access its action hash easily\nconst actionHash: ActionHash = profileRecord.actionHash;\n```\n\n##  RecordBag\n\nUtility to type a list of `Records` and extract useful information from them.\n\n```ts\nimport { Record } from '@holochain/client';\nimport { RecordBag } from '@darksoil-studio/holochain-utils';\n\n// Imagine a zome function that returns a list of records,\n// but we know their entry type\nconst records: Record[] = await callZome(...);          \n\n// Then we can type it\nconst profiles = new RecordBag<Profile>(records);\n\n// Map of entry hash -> entry\nconst profileEntries: EntryHashMap<Profile> = profiles.entryMap; \n\n// Map of action hash -> action\n// Timestamps are in milliseconds\nconst profileActions: ActionHashMap<Action> = profiles.actionMap;\n\n// Map of entry hash -> all the actions that have created or updated to that entry\nconst entryActions: EntryHashMap<ActionHash[]> = profiles.entryActions;\n\n// For each agent, contains all the actions it has authored\nconst authorMap: AgentPubKeyMap<ActionHash[]> = profiles.authorMap;\n\n// Get the array of all records\nconst profileEntries: Array<EntryRecord<Profile>> = profiles.entryRecords; \n```\n\n","readmeFilename":"README.md","_rev":"1-7b1801a79af97af52e4926512df44e3e"}