diff --git a/Cargo.lock b/Cargo.lock index d9da31c23..875f20995 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,18 +14,18 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ - "gimli 0.29.0", + "gimli 0.31.1", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "adler32" @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "aitia" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df16ceb7a48cd5b32ff6f5229ea89fad2e61b5f702a603d1ee4a2f2d2d3c6b3b" +checksum = "0c8d0d87e1228df0569cc160bb52542afaa7def9fcd248d1405febb400619126" dependencies = [ "anyhow", "derive_more", @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "app_dirs2" @@ -226,15 +226,15 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-attributes" @@ -271,14 +271,14 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.1.0", - "futures-lite 2.3.0", + "fastrand", + "futures-lite", "slab", ] @@ -290,59 +290,30 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.3.1", "async-executor", - "async-io 2.3.3", - "async-lock 3.4.0", + "async-io", + "async-lock", "blocking", - "futures-lite 2.3.0", + "futures-lite", "once_cell", ] [[package]] name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg 1.3.0", - "cfg-if 1.0.0", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "async-lock 3.4.0", + "async-lock", "cfg-if 1.0.0", "concurrent-queue", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "parking", - "polling 3.7.2", - "rustix 0.38.34", + "polling", + "rustix", "slab", "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", + "windows-sys 0.59.0", ] [[package]] @@ -358,25 +329,27 @@ dependencies = [ [[package]] name = "async-once-cell" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9338790e78aa95a416786ec8389546c4b6a1dfc3dc36071ed9518a9413a542eb" +checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" [[package]] name = "async-process" -version = "1.8.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ - "async-io 1.13.0", - "async-lock 2.8.0", + "async-channel 2.3.1", + "async-io", + "async-lock", "async-signal", + "async-task", "blocking", "cfg-if 1.0.0", - "event-listener 3.1.0", - "futures-lite 1.13.0", - "rustix 0.38.34", - "windows-sys 0.48.0", + "event-listener 5.3.1", + "futures-lite", + "rustix", + "tracing", ] [[package]] @@ -387,44 +360,44 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] name = "async-signal" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.3", - "async-lock 3.4.0", + "async-io", + "async-lock", "atomic-waker", "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix 0.38.34", + "rustix", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ "async-attributes", "async-channel 1.9.0", "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 1.13.0", + "futures-lite", "gloo-timers", "kv-log-macro", "log", @@ -465,13 +438,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -497,14 +470,14 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "automap" @@ -524,7 +497,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" dependencies = [ - "fastrand 2.1.0", + "fastrand", "futures-core", "pin-project", "tokio", @@ -532,17 +505,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -646,7 +619,7 @@ checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec", - "constant_time_eq 0.3.0", + "constant_time_eq 0.3.1", ] [[package]] @@ -667,7 +640,7 @@ dependencies = [ "async-channel 2.3.1", "async-task", "futures-io", - "futures-lite 2.3.0", + "futures-lite", "piper", ] @@ -712,9 +685,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.16.3" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -724,9 +697,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] @@ -769,9 +742,9 @@ checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] @@ -801,12 +774,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.7" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -842,6 +816,33 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.4.4" @@ -869,9 +870,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.13" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -879,9 +880,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.13" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -892,14 +893,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -960,9 +961,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "contrafact" @@ -998,9 +999,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -1017,7 +1018,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", "cfg-if 1.0.0", "libc", "scopeguard", @@ -1026,9 +1027,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1240,7 +1241,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -1262,7 +1263,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -1296,9 +1297,9 @@ dependencies = [ [[package]] name = "dashmap" -version = "6.0.1" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1343,7 +1344,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -1357,11 +1358,11 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "derive_builder_macro 0.20.0", + "derive_builder_macro 0.20.2", ] [[package]] @@ -1378,14 +1379,14 @@ dependencies = [ [[package]] name = "derive_builder_core" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -1400,12 +1401,12 @@ dependencies = [ [[package]] name = "derive_builder_macro" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "derive_builder_core 0.20.0", - "syn 2.0.72", + "derive_builder_core 0.20.2", + "syn 2.0.79", ] [[package]] @@ -1418,7 +1419,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -1473,7 +1474,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -1566,7 +1567,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -1638,17 +1639,6 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" -[[package]] -name = "event-listener" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - [[package]] name = "event-listener" version = "5.3.1" @@ -1690,29 +1680,20 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -1723,9 +1704,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "fixt" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00a24e34fdd8f793f4eb4e507c8dde88f6c560c19ad337c2fb1f82bb11613cd" +checksum = "ed8befecee7e4e63c317ab8acbc953c4aceb55e12a3a28b51b40dbb627562ae6" dependencies = [ "holochain_serialized_bytes", "lazy_static", @@ -1740,9 +1721,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -1763,6 +1744,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1807,9 +1794,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1822,9 +1809,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1832,15 +1819,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1849,24 +1836,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1874,7 +1846,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.1.0", + "fastrand", "futures-core", "futures-io", "parking", @@ -1883,26 +1855,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -1912,9 +1884,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -2040,15 +2012,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -2085,7 +2057,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.3.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2094,9 +2066,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -2104,7 +2076,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.3.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2113,9 +2085,13 @@ dependencies = [ [[package]] name = "half" -version = "1.8.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if 1.0.0", + "crunchy", +] [[package]] name = "hashbrown" @@ -2124,7 +2100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" dependencies = [ "ahash 0.3.8", - "autocfg 1.3.0", + "autocfg 1.4.0", ] [[package]] @@ -2146,6 +2122,17 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "hashlink" version = "0.9.1" @@ -2183,9 +2170,9 @@ dependencies = [ [[package]] name = "hc_sleuth" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89308367812f00b6de1b0682129d23e2fcc3a6d1ae7877d68744c4a63957a627" +checksum = "60d2cec326f6b4fd869e86d79a698589a7e0898b16d7b2675f2733770d28acad" dependencies = [ "aitia", "anyhow", @@ -2224,14 +2211,15 @@ version = "0.2.0" dependencies = [ "derive_more", "hdi", + "profiles_types", "serde", ] [[package]] name = "hdi" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece9b147d5e9ebc0a1f47a180a31436f4390a060ad46aa325d1fb851321ec3c7" +checksum = "f6a494d33e1082b380b8163ace83d53ca39ca053d0f45f6997d13a8fca008a35" dependencies = [ "getrandom 0.2.15", "hdk_derive", @@ -2247,9 +2235,9 @@ dependencies = [ [[package]] name = "hdk" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ba518e916e7eb29cf4a3b4c0d853fefab76bffc19939f8e0e5925581c67da7" +checksum = "26d6fef9a03facd811accc5a1bb1e22a577e4875190b53337ff01b4746463c78" dependencies = [ "getrandom 0.2.15", "hdi", @@ -2267,9 +2255,9 @@ dependencies = [ [[package]] name = "hdk_derive" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93b26f45db67e2619836cd70a880bcf46d40ef844cd838d99ef6008e0f84e86c" +checksum = "4d00472129b62df85a0c853e7ce8cbd4a868e8cf2a30896c470176500d887795" dependencies = [ "darling 0.14.4", "heck 0.5.0", @@ -2370,9 +2358,9 @@ dependencies = [ [[package]] name = "holo_hash" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acfa694a0138aafda54ce76033168cf182158b7628f7e70b12af0ea0ad20d896" +checksum = "f68f60591ed381388f46c59351a6e2c3d77cb1409a94200dbfd423a6bb8a3622" dependencies = [ "arbitrary", "base64 0.22.1", @@ -2396,9 +2384,9 @@ dependencies = [ [[package]] name = "holochain" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1eb75811baa0598d13a0b01d0b0becc54e26efda9effc20a03e9557367e3d0c" +checksum = "94681f4ca30845b27f44cb751a8db6a0cef266dc45c8a44ba0c3af95550403d4" dependencies = [ "aitia", "anyhow", @@ -2496,9 +2484,9 @@ dependencies = [ [[package]] name = "holochain_cascade" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3119db52d092b333947dacf9aec95d99a7eadc8eda1a2bc97730e77bafe034ae" +checksum = "30641ba03a9abb8d7793690f07d3b626ddf4c963d1fb1ad6ab3be213cb6d76bf" dependencies = [ "async-trait", "fixt", @@ -2523,9 +2511,9 @@ dependencies = [ [[package]] name = "holochain_conductor_api" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172baa045723827a37d066b2c564e231689abf4570fe512f07778dc0c78d7c8a" +checksum = "2beb2ef85e53cb2567ad6cd555bb0566394b34ffbc4b090715bbebbb167d20cc" dependencies = [ "derive_more", "holo_hash", @@ -2546,9 +2534,9 @@ dependencies = [ [[package]] name = "holochain_conductor_services" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "734cf4cd51642e97e3a7b4085e969a09aa6f6236b3a72b964a8df30b71704793" +checksum = "dfea6be130982205a5421648245a678d429724aaeaf1a61157f3652ccc823355" dependencies = [ "anyhow", "async-trait", @@ -2562,12 +2550,12 @@ dependencies = [ [[package]] name = "holochain_integrity_types" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3c84cd0ee02fa15e037df4fd81c170cb956792732823416c61b0f4e3d2e177" +checksum = "dbb39eaaff334d30de7c7ff547e9f68490098fe379e747852367e508ac485cb3" dependencies = [ "arbitrary", - "derive_builder 0.20.0", + "derive_builder 0.20.2", "holo_hash", "holochain_secure_primitive", "holochain_serialized_bytes", @@ -2584,9 +2572,9 @@ dependencies = [ [[package]] name = "holochain_keystore" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571f76a5f5d229ce854f9f7757f42db4767ed3248ac886396776450970300979" +checksum = "d15bc60dc779fbfd3a99dc3e37f2c5e9eb9c10d3109f70237d6b3d5f69c1c82b" dependencies = [ "base64 0.22.1", "derive_more", @@ -2613,9 +2601,9 @@ dependencies = [ [[package]] name = "holochain_metrics" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6811d3b83553ef9e3369b79e67955d978af0b7503d2393805c220342bf3b985" +checksum = "a74d7492154a24290d96edfd7548dd895d6f66d9b80a2b9f9a256ef7a8e9b37f" dependencies = [ "influxive", "opentelemetry_api", @@ -2624,9 +2612,9 @@ dependencies = [ [[package]] name = "holochain_nonce" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbbb63a7658f55a0640a04ad675d7dc6979b7eb7f0a889882efa6e9ac95fd606" +checksum = "7342ca1e823909779cba6f7c0338c82f150957a10ef9931befaf7d75454c6bb7" dependencies = [ "getrandom 0.2.15", "holochain_secure_primitive", @@ -2635,9 +2623,9 @@ dependencies = [ [[package]] name = "holochain_p2p" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bfde1589d00397861464f9234b8877b2e821f8f5fa6c0217070a0fee77e7bf7" +checksum = "e0c0bbefdccba24a52dc3d25355f7280cf4a15c21bf5bb592b7d5acadaffafb5" dependencies = [ "aitia", "async-trait", @@ -2667,9 +2655,9 @@ dependencies = [ [[package]] name = "holochain_secure_primitive" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2495193fe4700ccd3fda02acc7f982890938b28deb264c9212df3868efd9e0e" +checksum = "023dd96581cb629abc8089a6a583ad4fd47336c2600f8f1bad0035229b35e260" dependencies = [ "paste", "serde", @@ -2706,9 +2694,9 @@ dependencies = [ [[package]] name = "holochain_sqlite" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8b43b7ffd327ded81ff3b5851bbe24757d2822fe288d5b018516ce371a86a4" +checksum = "f986b3437bf22037f9372ac9db9e74e571bd4b7957b0a26cc4a339de3866f8af" dependencies = [ "anyhow", "async-trait", @@ -2749,9 +2737,9 @@ dependencies = [ [[package]] name = "holochain_state" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4bbe822026fb0afda545a22b4e1aa98b7470072806b47af71bafc716f6ea39" +checksum = "6ef99f9cfb8a0821b921d6be151797cb6fcec9ad5e27120f6d7b8b65a6d2c7ec" dependencies = [ "aitia", "async-recursion", @@ -2785,9 +2773,9 @@ dependencies = [ [[package]] name = "holochain_state_types" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f876726313c8373f2c0934eb1f9fd1cff99f94c51281898779daa1ba22ba4a4" +checksum = "7ea98b0b2e8f51a83d617e194d1a73271e348a52b2f3f371cf860ec9e05e8746" dependencies = [ "holo_hash", "holochain_integrity_types", @@ -2796,9 +2784,9 @@ dependencies = [ [[package]] name = "holochain_test_wasm_common" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3e521892e6aa14cb856f373e0b2a9deaca5923e1f06de3b92fc89e9b1c44fb" +checksum = "82276c8e0305deabd77c5f3405bef0aa99448a3f6e5f60f84e7069dee73c953b" dependencies = [ "hdk", "serde", @@ -2806,9 +2794,9 @@ dependencies = [ [[package]] name = "holochain_trace" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a1fa6e79b0774ef51faf34213abd620dc80caa9da0e4f3ff4e64b85be7a9416" +checksum = "91445161ac030d586669207807cb165e6943e7e56aeda485476fc020ffa99f62" dependencies = [ "chrono", "derive_more", @@ -2824,9 +2812,9 @@ dependencies = [ [[package]] name = "holochain_types" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cd76009a50e6155adc650741b8188188abe4d3daff8666864ef808d314d9e6d" +checksum = "1f5a24d9090e7288d7abba810c87c73a63b6f940cee264c4c98a0951e85d047c" dependencies = [ "anyhow", "arbitrary", @@ -2834,7 +2822,7 @@ dependencies = [ "automap", "backtrace", "contrafact", - "derive_builder 0.20.0", + "derive_builder 0.20.2", "derive_more", "fixt", "flate2", @@ -2878,9 +2866,9 @@ dependencies = [ [[package]] name = "holochain_util" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df91c909ed1bcf3dfc55db8dfa8361dba9c4e518c80f9cd30b5c00a3e9c84c62" +checksum = "4fa1fbf85e159b07bac3bb9596f9af5ca79e8e31f83c47a70f8517fd945bcd04" dependencies = [ "backtrace", "cfg-if 1.0.0", @@ -2896,9 +2884,9 @@ dependencies = [ [[package]] name = "holochain_wasm_test_utils" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1333cd0ba272e3191489e52538a3b787f294ca81ccf3b6e0d3839be5cf3fca4" +checksum = "6a98d7627be51e9f40447773f5c843c14c47187436ea832ff95212385320b0ea" dependencies = [ "holochain_types", "holochain_util", @@ -2957,9 +2945,9 @@ dependencies = [ [[package]] name = "holochain_websocket" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e211a00967a0e7796fcd43b28a7109d92d44ff19266cf08a2da40e62e7a33f" +checksum = "41096273a68c09422a30a744902406a19abdc122899a6b11474dba4e1b35e05e" dependencies = [ "async-trait", "futures", @@ -2974,13 +2962,13 @@ dependencies = [ [[package]] name = "holochain_zome_types" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "526a51ed0b962c2579ff57106fe2dd032a9a1cf2e4820f3dc2f2b37a59b0cc66" +checksum = "9e7cb5c0a7d7162bb3f3fe96e4fb63b31da47a11aa3f3d509e44b78ca4920382" dependencies = [ "arbitrary", "contrafact", - "derive_builder 0.20.0", + "derive_builder 0.20.2", "derive_more", "fixt", "holo_hash", @@ -3098,9 +3086,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -3110,9 +3098,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "human-panic" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c5a08ed290eac04006e21e63d32e90086b6182c7cd0452d10f4264def1fec9a" +checksum = "80b84a66a325082740043a6c28bbea400c129eac0d3a27673a1de971e44bf1f7" dependencies = [ "anstream", "anstyle", @@ -3157,7 +3145,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.5", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "httparse", @@ -3184,15 +3172,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", "hyper 1.4.1", "hyper-util", - "rustls 0.23.12", + "rustls 0.23.14", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -3230,9 +3218,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", @@ -3243,16 +3231,15 @@ dependencies = [ "pin-project-lite", "socket2 0.5.7", "tokio", - "tower", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3329,19 +3316,19 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", "hashbrown 0.12.3", "serde", ] [[package]] name = "indexmap" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "serde", ] @@ -3352,12 +3339,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash 0.8.11", - "clap 4.5.13", + "clap 4.5.20", "crossbeam-channel", "crossbeam-utils", - "dashmap 6.0.1", + "dashmap 6.1.0", "env_logger", - "indexmap 2.3.0", + "indexmap 2.6.0", "is-terminal", "itoa", "log", @@ -3502,30 +3489,19 @@ dependencies = [ "trilean", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.4.0", "libc", "windows-sys 0.52.0", ] @@ -3612,18 +3588,18 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] name = "kitsune_p2p" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "820f8c4b6fe9c5282361ebce22b9b355e3a6f3f0259acf8b585f1d46c503ca12" +checksum = "d139523575868a1a8ed109556db5a1004ccc5d5a2e6e3bf62f6bad3777c6150c" dependencies = [ "arrayref", "base64 0.22.1", @@ -3668,9 +3644,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_bin_data" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d57481371cae8f3afdc4f8b0791aa04c70afe375c8678ca2bf966637220b6a" +checksum = "33f6e27475c31b3492ba78dbc0e945798cf00d7489def5e574f1ff26ab7cdffb" dependencies = [ "arbitrary", "base64 0.22.1", @@ -3687,9 +3663,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_block" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10105ffc84c408d89a39180460fa9adcfcff09dedb511703efdab050fdbfe40c" +checksum = "9bf0b3a417771c4d5268cb211a2aba64d495091868f990c7e728362aab7c8f6d" dependencies = [ "kitsune_p2p_bin_data", "kitsune_p2p_timestamp", @@ -3698,17 +3674,17 @@ dependencies = [ [[package]] name = "kitsune_p2p_bootstrap" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819b705dd8ef03a47b7d1d5df604cead7be890fcea864d028212252baa8ae649" +checksum = "82389b98b00346c7f92248fb73825c083720fb729748a6c184e7da938b1c41d0" dependencies = [ - "clap 4.5.13", + "clap 4.5.20", "futures", "kitsune_p2p_bin_data", "kitsune_p2p_types", "parking_lot 0.12.3", "rand 0.8.5", - "reqwest 0.12.5", + "reqwest 0.12.8", "serde", "serde_bytes", "thiserror", @@ -3718,14 +3694,14 @@ dependencies = [ [[package]] name = "kitsune_p2p_bootstrap_client" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af44ba9ef97b6e00c99c8762d679eaa209e933e1e6fc517ef8df8a8134f1b3f7" +checksum = "3a1c01931a38d0e09927bcf78040fc97de35491c96be63352c0c4371af9a7e57" dependencies = [ "kitsune_p2p_bin_data", "kitsune_p2p_bootstrap", "kitsune_p2p_types", - "reqwest 0.12.5", + "reqwest 0.12.8", "serde", "serde_bytes", "url2", @@ -3733,9 +3709,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_dht" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e09eb5fefd76459e8417234dff5170dcc40c6bddfe56d84d59d1b1867e4378" +checksum = "57f1f73203977efe3cc1141a959b07b29d82220f211955f14f72e5731ac8cb05" dependencies = [ "arbitrary", "colored", @@ -3757,9 +3733,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_dht_arc" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6be19fb54f5f3adb7ef461d51d073f22f3e7343952a31523d04799bceb695ee2" +checksum = "b703d57c74b2a3d187ec3bbd2be8cf0f52c8d8e1059f5ba3c0d23218f6504e84" dependencies = [ "arbitrary", "derive_more", @@ -3775,13 +3751,13 @@ dependencies = [ [[package]] name = "kitsune_p2p_fetch" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbafc5fb36c8940989b6d8c4ea02aec09efc4f195e79d4532b5bdb363bbec1d2" +checksum = "e6550ea608b633ac295a545c84fb7ff435c263b80a4b16907ab6aace6ac4ae15" dependencies = [ "backon", "derive_more", - "indexmap 2.3.0", + "indexmap 2.6.0", "kitsune_p2p_timestamp", "kitsune_p2p_types", "serde", @@ -3791,9 +3767,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_mdns" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17854121a83e6694bd890c869fa7e511449131495c0ad954c13409f2fc8e7b5e" +checksum = "305236dcbbd2c48d03c29ce430bd8319f7c7e4c64790f97bdb4337238871393b" dependencies = [ "base64 0.22.1", "err-derive 0.3.1", @@ -3806,9 +3782,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_proxy" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c6aa7991351145e7ee372777335851290dbec181d4defa7b266e88778c4c6a" +checksum = "f571aa38f61733d1e6a41d35cc08f514a5616039363a47ea7e92d4dd958ccbd1" dependencies = [ "base64 0.22.1", "derive_more", @@ -3824,9 +3800,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_timestamp" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f0ae9c213de76b54f2a7fcfd1f379b106b45efef1c4365110d7df96a531d69e" +checksum = "dade104770176570d49fc70d56801f81e0969b440b71f92ed5ea99746da4932f" dependencies = [ "arbitrary", "chrono", @@ -3840,9 +3816,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_transport_quic" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcda54a6237011a388f0d4bc2a63eb4011927c08dc805fbb41139414c86f1ca9" +checksum = "5702ab51e38eccf842e626cfa785f8e6765ac201ed3251b6a6a284d543bd09a0" dependencies = [ "blake2b_simd", "futures", @@ -3856,9 +3832,9 @@ dependencies = [ [[package]] name = "kitsune_p2p_types" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5466b1e18532035c7bdb3347362463943ed3c7896e2970ba224896f9a2556540" +checksum = "46c0cd7db3b403856bcaebc6a781782bb94350e24cfec2d9296a1518310f1a28" dependencies = [ "arbitrary", "base64 0.22.1", @@ -3955,9 +3931,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libflate" @@ -4027,13 +4003,14 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", + "redox_syscall 0.5.7", ] [[package]] name = "libsodium-sys-stable" -version = "1.21.1" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd1882b85f01cdd4021c0664fd897710a04c5d01b593a5a70e1b0baa999c1f8" +checksum = "42631d334de875c636a1aae7adb515653ac2e771e5a2ce74b1053f5a4412df3a" dependencies = [ "cc", "libc", @@ -4043,7 +4020,7 @@ dependencies = [ "tar", "ureq", "vcpkg", - "zip 2.1.6", + "zip 2.2.0", ] [[package]] @@ -4058,12 +4035,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -4082,7 +4053,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", "scopeguard", ] @@ -4103,11 +4074,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -4161,7 +4132,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", "rawpointer", ] @@ -4211,7 +4182,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", ] [[package]] @@ -4220,7 +4191,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", ] [[package]] @@ -4247,24 +4218,24 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "minisign-verify" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" +checksum = "a05b5d0594e0cb1ad8cee3373018d2b84e25905dc75b2468114cc9a8e86cfc20" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", @@ -4307,9 +4278,9 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "mr_bundle" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2343770ce615ec247e0089a8eaae5731809493a708ac244e187e43a005fb1987" +checksum = "032b2adeb25720b79d7a18ae93dc53a9719e93e6eb707f12b53898b6b4e3febb" dependencies = [ "arbitrary", "derive_more", @@ -4318,7 +4289,7 @@ dependencies = [ "holochain_util", "proptest", "proptest-derive 0.5.0", - "reqwest 0.12.5", + "reqwest 0.12.8", "rmp-serde", "serde", "serde_bytes", @@ -4563,7 +4534,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", "num-integer", "num-traits", ] @@ -4585,7 +4556,7 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", "libm", ] @@ -4617,23 +4588,23 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] name = "object" -version = "0.36.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "one_err" @@ -4670,7 +4641,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -4681,9 +4652,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.3.1+3.3.1" +version = "300.3.2+3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91" +checksum = "a211a18d945ef7e648cc6e0058f4c548ee46aab922ea203e0d30e966ea23647b" dependencies = [ "cc", ] @@ -4765,9 +4736,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -4812,7 +4783,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.3", + "redox_syscall 0.5.7", "smallvec", "windows-targets 0.52.6", ] @@ -4863,9 +4834,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", "thiserror", @@ -4879,28 +4850,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.3.0", + "indexmap 2.6.0", "quickcheck", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -4917,50 +4888,34 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.1.0", + "fastrand", "futures-io", ] [[package]] name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "polling" -version = "2.8.0" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg 1.3.0", - "bitflags 1.3.2", - "cfg-if 1.0.0", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "polling" -version = "3.7.2" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.34", + "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5024,9 +4979,9 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -5034,11 +4989,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.21.1", + "toml_edit", ] [[package]] @@ -5067,13 +5022,22 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiles_types" +version = "0.2.0" +dependencies = [ + "derive_more", + "hdi", + "serde", +] + [[package]] name = "prometheus" version = "0.13.4" @@ -5103,7 +5067,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift 0.3.0", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "rusty-fork", "tempfile", "unarray", @@ -5128,7 +5092,7 @@ checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -5247,9 +5211,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -5535,27 +5499,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", "libredox", @@ -5576,14 +5531,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -5597,13 +5552,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -5614,9 +5569,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "region" @@ -5670,7 +5625,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio", "tokio-native-tls", "tokio-rustls 0.24.1", @@ -5682,26 +5637,26 @@ dependencies = [ "wasm-streams", "web-sys", "webpki-roots 0.25.4", - "winreg 0.50.0", + "winreg", ] [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.4.5", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "http-body-util", "hyper 1.4.1", - "hyper-rustls 0.27.2", + "hyper-rustls 0.27.3", "hyper-tls 0.6.0", "hyper-util", "ipnet", @@ -5712,12 +5667,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.1.3", + "rustls-pemfile 2.2.0", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", - "system-configuration", + "system-configuration 0.6.1", "tokio", "tokio-native-tls", "tower-service", @@ -5725,14 +5680,14 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.52.0", + "windows-registry", ] [[package]] name = "rgb" -version = "0.8.45" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade4539f42266ded9e755c605bdddf546242b2c961b03b06a7375260788a0523" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -5769,9 +5724,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ "bitvec", "bytecheck", @@ -5788,9 +5743,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ "proc-macro2", "quote", @@ -5880,37 +5835,23 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver 1.0.23", ] [[package]] name = "rustix" -version = "0.37.27" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.14", + "linux-raw-sys", "windows-sys 0.52.0", ] @@ -5940,13 +5881,13 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ "once_cell", "rustls-pki-types", - "rustls-webpki 0.102.6", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] @@ -5983,19 +5924,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" [[package]] name = "rustls-webpki" @@ -6019,9 +5959,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -6072,11 +6012,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6110,7 +6050,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -6137,9 +6077,9 @@ dependencies = [ [[package]] name = "sd-notify" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4646d6f919800cd25c50edb49438a1381e2cd4833c027e75e8897981c50b8b5e" +checksum = "1be20c5f7f393ee700f8b2f28ea35812e4e212f40774b550cd2a93ea91684451" [[package]] name = "seahash" @@ -6162,9 +6102,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -6241,16 +6181,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - [[package]] name = "serde_derive" version = "1.0.203" @@ -6259,7 +6189,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -6270,16 +6200,16 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.6.0", "itoa", "memchr", "ryu", @@ -6288,9 +6218,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -6309,15 +6239,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.3.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -6327,14 +6257,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -6343,7 +6273,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.6.0", "itoa", "ryu", "serde", @@ -6402,6 +6332,12 @@ dependencies = [ "memmap2 0.6.2", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "shrinkwraprs" version = "0.3.0" @@ -6445,9 +6381,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" @@ -6464,7 +6400,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg 1.3.0", + "autocfg 1.4.0", ] [[package]] @@ -6528,9 +6464,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "sqlformat" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" dependencies = [ "nom", "unicode_categories", @@ -6588,7 +6524,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -6599,7 +6535,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -6695,9 +6631,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -6715,6 +6651,9 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "synstructure" @@ -6751,7 +6690,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -6764,6 +6714,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tap" version = "1.0.1" @@ -6772,9 +6732,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020" dependencies = [ "filetime", "libc", @@ -6801,25 +6761,25 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.11.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if 1.0.0", - "fastrand 2.1.0", + "fastrand", "once_cell", - "rustix 0.38.34", - "windows-sys 0.52.0", + "rustix", + "windows-sys 0.59.0", ] [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" dependencies = [ - "rustix 0.38.34", - "windows-sys 0.48.0", + "rustix", + "windows-sys 0.59.0", ] [[package]] @@ -6894,7 +6854,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -6908,22 +6868,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -6993,9 +6953,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -7017,7 +6977,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -7057,16 +7017,16 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.12", + "rustls 0.23.14", "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -7104,9 +7064,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -7124,7 +7084,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.20", + "toml_edit", ] [[package]] @@ -7138,26 +7098,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.3.0", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.18", + "winnow", ] [[package]] @@ -7173,32 +7122,11 @@ dependencies = [ "walkdir", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -7220,7 +7148,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -7468,7 +7396,7 @@ version = "0.0.14-alpha" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afa882b51d1c4b4e86c9a43134674b856a8248c147d889c70c6d0f9d88541012" dependencies = [ - "clap 4.5.13", + "clap 4.5.20", "dirs", "futures", "if-addrs 0.10.2", @@ -7491,9 +7419,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unarray" @@ -7512,42 +7440,42 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unicode_categories" @@ -7592,9 +7520,9 @@ dependencies = [ [[package]] name = "ureq" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72139d247e5f97a3eff96229a7ae85ead5328a39efe76f8bf5a06313d505b6ea" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ "base64 0.22.1", "log", @@ -7692,12 +7620,6 @@ dependencies = [ "libc", ] -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - [[package]] name = "walkdir" version = "2.5.0" @@ -7760,34 +7682,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if 1.0.0", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -7797,9 +7720,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7807,22 +7730,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-encoder" @@ -7835,9 +7758,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ "futures-util", "js-sys", @@ -7924,19 +7847,19 @@ dependencies = [ [[package]] name = "wasmer-config" -version = "0.4.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4a632496950fde9ad821e195ef1a301440076f7c7d80de55239a140359bcbd" +checksum = "644b7e3547bd7e796d92220f60bf57734914254c6cee56607e80177a3e8a28da" dependencies = [ "anyhow", "bytesize", + "ciborium", "derive_builder 0.12.0", "hex", - "indexmap 2.3.0", + "indexmap 2.6.0", "schemars", "semver 1.0.23", "serde", - "serde_cbor", "serde_json", "serde_yaml", "thiserror", @@ -8023,7 +7946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ "bitflags 2.6.0", - "indexmap 2.3.0", + "indexmap 2.6.0", "semver 1.0.23", ] @@ -8050,9 +7973,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -8060,14 +7983,15 @@ dependencies = [ [[package]] name = "webc" -version = "6.0.0-rc2" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3e2ccb43d303c5bd48f31db7a129481a9aaa5343d623f92951751df190df81" +checksum = "cdea84cf234555864ca9b7a5084c1a99dbdf2d148035f62a09b19ce5606532c1" dependencies = [ "anyhow", "base64 0.22.1", "bytes", "cfg-if 1.0.0", + "ciborium", "document-features", "flate2", "indexmap 1.9.3", @@ -8075,7 +7999,6 @@ dependencies = [ "once_cell", "semver 1.0.23", "serde", - "serde_cbor", "serde_json", "sha2", "shared-buffer", @@ -8114,9 +8037,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "wide" -version = "0.7.26" +version = "0.7.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901e8597c777fa042e9e245bd56c0dc4418c5db3f845b6ff94fbac732c6a0692" +checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690" dependencies = [ "bytemuck", "safe_arch", @@ -8178,6 +8101,36 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.33.0" @@ -8437,18 +8390,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.40" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -8463,16 +8407,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if 1.0.0", - "windows-sys 0.48.0", -] - [[package]] name = "wyz" version = "0.5.1" @@ -8489,8 +8423,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", - "linux-raw-sys 0.4.14", - "rustix 0.38.34", + "linux-raw-sys", + "rustix", ] [[package]] @@ -8507,9 +8441,9 @@ checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yasna" @@ -8538,7 +8472,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.79", ] [[package]] @@ -8569,16 +8503,16 @@ dependencies = [ [[package]] name = "zip" -version = "2.1.6" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40dd8c92efc296286ce1fbd16657c5dbefff44f1b4ca01cc5f517d8b7b3d3e2e" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", "crc32fast", "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.3.0", + "indexmap 2.6.0", "memchr", "thiserror", "zopfli", diff --git a/crates/coordinator/src/lib.rs b/crates/coordinator/src/lib.rs index f7297edb0..1616d26ec 100644 --- a/crates/coordinator/src/lib.rs +++ b/crates/coordinator/src/lib.rs @@ -11,199 +11,10 @@ use hdk::prelude::*; use hc_zome_profiles_integrity::*; -/// Creates the profile for the agent executing this call. -#[hdk_extern] -pub fn create_profile(profile: Profile) -> ExternResult { - let agent_info = agent_info()?; - - let action_hash = create_entry(EntryTypes::Profile(profile.clone()))?; - - let path = prefix_path(profile.nickname.clone())?; - - path.ensure()?; - - let agent_address = agent_info.agent_initial_pubkey; - - create_link( - path.path_entry_hash()?, - agent_address.clone(), - LinkTypes::PathToAgent, - LinkTag::new(profile.nickname.to_lowercase().as_bytes().to_vec()), - )?; - create_link( - agent_address, - action_hash.clone(), - LinkTypes::AgentToProfile, - (), - )?; - - let record = get(action_hash, GetOptions::default())? - .ok_or(wasm_error!(WasmErrorInner::Guest("Unreachable".into())))?; - - Ok(record) -} - -/// Updates the profile for the agent executing this call. -#[hdk_extern] -pub fn update_profile(profile: Profile) -> ExternResult { - let previous_profile_record = crate::get_agent_profile(agent_info()?.agent_latest_pubkey)? - .ok_or(wasm_error!(WasmErrorInner::Guest( - "I haven't created a profile yet".into(), - )))?; - - let action_hash = update_entry(previous_profile_record.action_address().clone(), &profile)?; - let my_pub_key = agent_info()?.agent_latest_pubkey; - - // If we have changed the nickname, remove the previous nickname link and add a new one - let previous_profile: Profile = previous_profile_record - .entry() - .to_app_option() - .map_err(|e| wasm_error!(e))? - .ok_or(wasm_error!(WasmErrorInner::Guest( - "Previous profile is malformed".to_string() - )))?; - if previous_profile.nickname.ne(&profile.nickname) { - let previous_prefix_path = prefix_path(previous_profile.nickname)?; - let links = get_links( - GetLinksInputBuilder::try_new( - previous_prefix_path.path_entry_hash()?, - LinkTypes::PathToAgent.try_into_filter()?, - )? - .build(), - )?; - - for l in links { - if let Ok(pub_key) = AgentPubKey::try_from(l.target) { - if my_pub_key.eq(&pub_key) { - delete_link(l.create_link_hash)?; - } - } - } - - let path = prefix_path(profile.nickname.clone())?; - - path.ensure()?; - - create_link( - path.path_entry_hash()?, - my_pub_key, - LinkTypes::PathToAgent, - LinkTag::new(profile.nickname.to_lowercase().as_bytes().to_vec()), - )?; - } - - let record = get(action_hash, GetOptions::default())? - .ok_or(wasm_error!(WasmErrorInner::Guest("Unreachable".into())))?; - - Ok(record) -} - -/// From a nickname filter of at least 3 characters, returns all the agents whose nickname starts with that prefix -/// Ignores the nickname case, will return upper or lower case nicknames that match -#[hdk_extern] -pub fn search_agents(nickname_filter: String) -> ExternResult> { - if nickname_filter.len() < 3 { - return Err(wasm_error!(WasmErrorInner::Guest( - "Cannot search with a prefix less than 3 characters".into(), - ))); - } - - let prefix_path = prefix_path(nickname_filter.clone())?; - let links = get_links( - GetLinksInputBuilder::try_new( - prefix_path.path_entry_hash()?, - LinkTypes::PathToAgent.try_into_filter()?, - )? - .tag_prefix(LinkTag::new( - nickname_filter.to_lowercase().as_bytes().to_vec(), - )) - .build(), - )?; - - let mut agents: Vec = vec![]; - - for link in links { - if let Ok(pub_key) = AgentPubKey::try_from(link.target) { - agents.push(pub_key); - } - } - - Ok(agents) -} - -/// Returns the profile for the given agent, if they have created it. -#[hdk_extern] -pub fn get_agent_profile(agent_pub_key: AgentPubKey) -> ExternResult> { - let links = get_links( - GetLinksInputBuilder::try_new(agent_pub_key, LinkTypes::AgentToProfile.try_into_filter()?)? - .build(), - )?; - - if links.is_empty() { - return Ok(None); - } - - let link = links[0].clone(); - - let profile = get_latest(link.target.into_action_hash().ok_or(wasm_error!( - WasmErrorInner::Guest("Profile link target is not of ActionHash".into()) - ))?)?; - - Ok(Some(profile)) -} - -fn get_latest(action_hash: ActionHash) -> ExternResult { - let details = get_details(action_hash, GetOptions::default())?.ok_or(wasm_error!( - WasmErrorInner::Guest("Profile not found".into()) - ))?; - - match details { - Details::Entry(_) => Err(wasm_error!(WasmErrorInner::Guest( - "Malformed details".into() - ))), - Details::Record(element_details) => match element_details.updates.last() { - Some(update) => get_latest(update.action_address().clone()), - None => Ok(element_details.record), - }, - } -} - -/// Gets all the agents that have created a profile in this DHT. -#[hdk_extern] -pub fn get_agents_with_profile(_: ()) -> ExternResult> { - let path = Path::from("all_profiles").typed(LinkTypes::PrefixPath)?; - - let children = path.children_paths()?; - - let get_links_input: Vec = children - .into_iter() - .map(|path| { - Ok(GetLinksInputBuilder::try_new( - path.path_entry_hash()?, - LinkTypes::PathToAgent.try_into_filter()?, - )? - .build()) - }) - .collect::>>()?; - - let links = HDK - .with(|h| h.borrow().get_links(get_links_input))? - .into_iter() - .flatten() - .collect::>(); - - Ok(links) -} - -/** Helpers*/ - -fn prefix_path(nickname: String) -> ExternResult { - // conver to lowercase for path for ease of search - let lower_nickname = nickname.to_lowercase(); - let prefix: String = lower_nickname.chars().take(3).collect(); - - Path::from(format!("all_profiles.{}", prefix)).typed(LinkTypes::PrefixPath) -} +mod link_agent; +mod profile_claims; +mod profiles; +mod search; #[derive(Serialize, Deserialize, Debug)] #[serde(tag = "type")] diff --git a/crates/coordinator/src/link_agent.rs b/crates/coordinator/src/link_agent.rs new file mode 100644 index 000000000..9f8cc5361 --- /dev/null +++ b/crates/coordinator/src/link_agent.rs @@ -0,0 +1,26 @@ +use hc_zome_profiles_integrity::LinkTypes; +use hdk::prelude::*; + +use crate::search::get_agent_profile; + +#[hdk_extern] +pub fn link_agent_with_my_profile(agent_pub_key: AgentPubKey) -> ExternResult<()> { + let my_profile_links = get_agent_profile(agent_info()?.agent_latest_pubkey)?; + + if my_profile_links.len() != 1 { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "Can't fetch my profile" + )))); + } + + let profile_link = my_profile_links[0].clone(); + let Some(profile_hash) = profile_link.target.into_action_hash() else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "Profile link does not have an ActionHash as its target" + )))); + }; + + create_link(agent_pub_key, profile_hash, LinkTypes::AgentToProfile, ())?; + + Ok(()) +} diff --git a/crates/coordinator/src/profile_claims.rs b/crates/coordinator/src/profile_claims.rs new file mode 100644 index 000000000..915b5d230 --- /dev/null +++ b/crates/coordinator/src/profile_claims.rs @@ -0,0 +1,40 @@ +use hdk::prelude::*; + +use hc_zome_profiles_integrity::*; + +#[hdk_extern] +pub fn create_profile_claim(profile_claim: ProfileClaim) -> ExternResult<()> { + create_relaxed(EntryTypes::ProfileClaim(profile_claim))?; + + Ok(()) +} +pub fn create_relaxed(entry_type: EntryTypes) -> ExternResult<()> { + HDK.with(|h| { + let index = ScopedEntryDefIndex::try_from(&entry_type)?; + let vis = EntryVisibility::from(&entry_type); + let entry = Entry::try_from(entry_type)?; + + h.borrow().create(CreateInput::new( + index, + vis, + entry, + // This is used to test many conductors thrashing creates between + // each other so we want to avoid retries that make the test take + // a long time. + ChainTopOrdering::Relaxed, + )) + })?; + + Ok(()) +} + +#[hdk_extern] +pub fn query_my_profile_claims() -> ExternResult> { + let filter = ChainQueryFilter::new() + .entry_type(UnitEntryTypes::ProfileClaim.try_into()?) + .include_entries(true) + .action_type(ActionType::Create); + let records = query(filter)?; + + Ok(records) +} diff --git a/crates/coordinator/src/profiles.rs b/crates/coordinator/src/profiles.rs new file mode 100644 index 000000000..90bccc7e7 --- /dev/null +++ b/crates/coordinator/src/profiles.rs @@ -0,0 +1,136 @@ +use hc_zome_profiles_integrity::*; +use hdk::prelude::*; + +use crate::search::prefix_path; + +/// Creates the profile for the agent executing this call. +#[hdk_extern] +pub fn create_profile(profile: Profile) -> ExternResult { + let agent_info = agent_info()?; + + let action_hash = create_entry(EntryTypes::Profile(profile.clone()))?; + + let path = prefix_path(profile.nickname.clone())?; + + path.ensure()?; + + let agent_address = agent_info.agent_initial_pubkey; + + create_link( + path.path_entry_hash()?, + action_hash.clone(), + LinkTypes::PathToProfile, + LinkTag::new(profile.nickname.to_lowercase().as_bytes().to_vec()), + )?; + create_link( + agent_address, + action_hash.clone(), + LinkTypes::AgentToProfile, + (), + )?; + + let record = get(action_hash, GetOptions::default())? + .ok_or(wasm_error!(WasmErrorInner::Guest("Unreachable".into())))?; + + Ok(record) +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct UpdateProfileInput { + previous_profile_hash: ActionHash, + updated_profile: Profile, +} + +/// Updates the profile for the agent executing this call. +#[hdk_extern] +pub fn update_profile(input: UpdateProfileInput) -> ExternResult { + let action_hash = update_entry(input.previous_profile_hash.clone(), &input.updated_profile)?; + let my_pub_key = agent_info()?.agent_latest_pubkey; + + let maybe_previous_profile_record = + get(input.previous_profile_hash.clone(), Default::default())?; + + let Some(previous_profile_record) = maybe_previous_profile_record else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "Could not get the previous profile" + )))); + }; + + // If we have changed the nickname, remove the previous nickname link and add a new one + let previous_profile: Profile = previous_profile_record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest( + "Previous profile is malformed".to_string() + )))?; + if previous_profile + .nickname + .ne(&input.updated_profile.nickname) + { + let previous_prefix_path = prefix_path(previous_profile.nickname)?; + let links = get_links( + GetLinksInputBuilder::try_new( + previous_prefix_path.path_entry_hash()?, + LinkTypes::PathToProfile.try_into_filter()?, + )? + .build(), + )?; + + for l in links { + if let Some(profile_hash) = l.target.into_action_hash() { + if input.previous_profile_hash.eq(&profile_hash) { + delete_link(l.create_link_hash)?; + } + } + } + + let path = prefix_path(input.updated_profile.nickname.clone())?; + + path.ensure()?; + + create_link( + path.path_entry_hash()?, + my_pub_key, + LinkTypes::PathToProfile, + LinkTag::new( + input + .updated_profile + .nickname + .to_lowercase() + .as_bytes() + .to_vec(), + ), + )?; + } + + let record = get(action_hash, GetOptions::default())? + .ok_or(wasm_error!(WasmErrorInner::Guest("Unreachable".into())))?; + + Ok(record) +} +#[hdk_extern] +pub fn get_original_profile(original_profile_hash: ActionHash) -> ExternResult> { + get(original_profile_hash, Default::default()) +} + +#[hdk_extern] +pub fn get_latest_profile(original_profile_hash: ActionHash) -> ExternResult> { + get_latest(original_profile_hash) +} + +fn get_latest(action_hash: ActionHash) -> ExternResult> { + let details = get_details(action_hash, GetOptions::default())?.ok_or(wasm_error!( + WasmErrorInner::Guest("Profile not found".into()) + ))?; + + match details { + Details::Entry(_) => Err(wasm_error!(WasmErrorInner::Guest( + "Malformed details".into() + ))), + Details::Record(record_details) => match record_details.updates.last() { + Some(update) => get_latest(update.action_address().clone()), + None => Ok(Some(record_details.record)), + }, + } +} diff --git a/crates/coordinator/src/search.rs b/crates/coordinator/src/search.rs new file mode 100644 index 000000000..1950983b6 --- /dev/null +++ b/crates/coordinator/src/search.rs @@ -0,0 +1,78 @@ +use hc_zome_profiles_integrity::*; +use hdk::prelude::*; + +/// From a nickname filter of at least 3 characters, returns all the profiles whose nickname starts with that prefix +/// Ignores the nickname case, will return upper or lower case nicknames that match +#[hdk_extern] +pub fn search_profiles(nickname_filter: String) -> ExternResult> { + if nickname_filter.len() < 3 { + return Err(wasm_error!(WasmErrorInner::Guest( + "Cannot search with a prefix less than 3 characters".into(), + ))); + } + + let prefix_path = prefix_path(nickname_filter.clone())?; + let links = get_links( + GetLinksInputBuilder::try_new( + prefix_path.path_entry_hash()?, + LinkTypes::PathToProfile.try_into_filter()?, + )? + .tag_prefix(LinkTag::new( + nickname_filter.to_lowercase().as_bytes().to_vec(), + )) + .build(), + )?; + + let action_hashes = links + .into_iter() + .filter_map(|link| link.target.into_action_hash()) + .collect(); + + Ok(action_hashes) +} + +/// Returns the links targeting the profiles for the given agent, must be one or 0 +#[hdk_extern] +pub fn get_agent_profile(agent_pub_key: AgentPubKey) -> ExternResult> { + get_links( + GetLinksInputBuilder::try_new(agent_pub_key, LinkTypes::AgentToProfile.try_into_filter()?)? + .build(), + ) +} + +/// Gets all the agents that have created a profile in this DHT. +#[hdk_extern] +pub fn get_all_profiles(_: ()) -> ExternResult> { + let path = Path::from("all_profiles").typed(LinkTypes::PrefixPath)?; + + let children = path.children_paths()?; + + let get_links_input: Vec = children + .into_iter() + .map(|path| { + Ok(GetLinksInputBuilder::try_new( + path.path_entry_hash()?, + LinkTypes::PathToProfile.try_into_filter()?, + )? + .build()) + }) + .collect::>>()?; + + let links = HDK + .with(|h| h.borrow().get_links(get_links_input))? + .into_iter() + .flatten() + .collect::>(); + + Ok(links) +} + +/** Helpers*/ + +pub fn prefix_path(nickname: String) -> ExternResult { + // conver to lowercase for path for ease of search + let lower_nickname = nickname.to_lowercase(); + let prefix: String = lower_nickname.chars().take(3).collect(); + + Path::from(format!("all_profiles.{}", prefix)).typed(LinkTypes::PrefixPath) +} diff --git a/crates/coordinator/tests/create_and_get.rs b/crates/coordinator/tests/create_and_get.rs deleted file mode 100644 index bf4bca87d..000000000 --- a/crates/coordinator/tests/create_and_get.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::collections::BTreeMap; - -use hc_zome_profiles_integrity::*; -use hdk::prelude::*; -use holochain::{conductor::config::ConductorConfig, sweettest::*}; - -#[tokio::test(flavor = "multi_thread")] -async fn create_and_get() { - // Use prebuilt DNA file - let dna_path = std::env::current_dir() - .unwrap() - .join(std::env::var("DNA_PATH").expect("DNA_PATH not set")); - let dna = SweetDnaFile::from_bundle(&dna_path).await.unwrap(); - - // Set up conductors - let mut conductors = SweetConductorBatch::from_config(2, ConductorConfig::default()).await; - let apps = conductors.setup_app("profiles", &[dna]).await.unwrap(); - conductors.exchange_peer_info().await; - - let ((alice,), (bobbo,)) = apps.into_tuples(); - - let alice_zome = alice.zome("profiles"); - let bob_zome = bobbo.zome("profiles"); - - let alice_pub_key = alice.agent_pubkey(); - - // Try to get my profile before creating one. Should return None. - let record_1: Option = conductors[0] - .call(&alice_zome, "get_agent_profile", alice_pub_key) - .await; - assert_eq!(record_1, None); - - // Create profile for alice and try to get it via get_my_profile() as well as get_agent_profile() - let profile = Profile { - nickname: String::from("alice"), - fields: BTreeMap::new(), - }; - - let record_1: Record = conductors[0] - .call(&alice_zome, "create_profile", profile) - .await; - - await_consistency(30, [&alice, &bobbo]).await.unwrap(); - - let record_2: Option = conductors[0] - .call(&alice_zome, "get_agent_profile", alice_pub_key) - .await; - - assert_eq!(record_1, record_2.unwrap()); - - let record_2: Option = conductors[1] - .call(&bob_zome, "get_agent_profile", alice.agent_pubkey()) - .await; - - assert_eq!(record_1, record_2.unwrap()); - - // Update alice's profile and again try to get it via get_my_profile() as well as get_agent_profile() - let profile = Profile { - nickname: String::from("alice2"), - fields: BTreeMap::new(), - }; - - let _record_1: Record = conductors[0] - .call(&alice_zome, "update_profile", profile.clone()) - .await; - - await_consistency(30, [&alice, &bobbo]).await.unwrap(); - - // ---> get it over the DHT though get_agent_profile() - let alices_profile: Option = conductors[1] - .call(&bob_zome, "get_agent_profile", alice.agent_pubkey()) - .await; - - if let Some(Record { - entry: RecordEntry::Present(entry), - .. - }) = alices_profile.clone() - { - let profile_entry = Profile::try_from(entry).unwrap(); - assert_eq!(profile_entry.nickname, profile.nickname); - } else { - panic!("Bad record"); - } - - // ---> get it from alice's source chain through get_my_profile() - let alices_profile_from_source_chain: Option = conductors[0] - .call(&alice_zome, "get_agent_profile", alice_pub_key) - .await; - - if let Some(Record { - entry: RecordEntry::Present(entry), - .. - }) = alices_profile_from_source_chain.clone() - { - let profile_entry = Profile::try_from(entry).unwrap(); - assert_eq!(profile_entry.nickname, profile.nickname); - } else { - panic!("Bad record"); - } - - // Create another profile for bob as well and call get_all_profiles() to check whether we get all two profiles - let _bobs_profile: Record = conductors[1] - .call( - &bob_zome, - "create_profile", - Profile { - nickname: "bob".into(), - fields: BTreeMap::new(), - }, - ) - .await; - - let all_agents: Vec = conductors[1] - .call(&bob_zome, "get_agents_with_profile", ()) - .await; - - assert_eq!(all_agents.len(), 2); -} diff --git a/crates/coordinator/tests/search.rs b/crates/coordinator/tests/search.rs deleted file mode 100644 index f507ef9ad..000000000 --- a/crates/coordinator/tests/search.rs +++ /dev/null @@ -1,77 +0,0 @@ -use std::collections::BTreeMap; - -use hc_zome_profiles_integrity::*; -use holochain::prelude::{AgentPubKey, Record}; -use holochain::{conductor::config::ConductorConfig, sweettest::*}; - -#[tokio::test(flavor = "multi_thread")] -async fn create_and_get() { - // Use prebuilt DNA file - let dna_path = std::env::current_dir() - .unwrap() - .join(std::env::var("DNA_PATH").expect("DNA_PATH not set")); - let dna = SweetDnaFile::from_bundle(&dna_path).await.unwrap(); - - // Set up conductors - let mut conductors = SweetConductorBatch::from_config(2, ConductorConfig::default()).await; - let apps = conductors.setup_app("profiles", &[dna]).await.unwrap(); - conductors.exchange_peer_info().await; - - let ((alice,), (bobbo,)) = apps.into_tuples(); - - let alice_zome = alice.zome("profiles"); - let bob_zome = bobbo.zome("profiles"); - - let profile = Profile { - nickname: String::from("ALIce"), - fields: BTreeMap::from([(String::from("avatar"), String::from("aliceavatar"))]), - }; - - let _alice_profile: Record = conductors[0] - .call(&alice_zome, "create_profile", profile) - .await; - let _bobs_profile: Record = conductors[1] - .call( - &bob_zome, - "create_profile", - Profile { - nickname: "bobbo".into(), - fields: BTreeMap::new(), - }, - ) - .await; - - await_consistency(30, [&alice, &bobbo]).await.unwrap(); - - let agents_searched: Vec = conductors[1] - .call(&bob_zome, "search_agents", String::from("ali")) - .await; - - assert_eq!(agents_searched.len(), 1); - assert_eq!(agents_searched[0], alice.agent_pubkey().clone()); - - let agents_searched: Vec = conductors[1] - .call(&bob_zome, "search_agents", String::from("alii")) - .await; - - assert_eq!(agents_searched.len(), 0); - - let agents_searched: Vec = conductors[1] - .call(&bob_zome, "search_agents", String::from("BoB")) - .await; - - assert_eq!(agents_searched.len(), 1); - assert_eq!(agents_searched[0], bobbo.agent_pubkey().clone()); - - let agents_searched: Vec = conductors[1] - .call(&bob_zome, "search_agents", String::from("asde")) - .await; - - assert_eq!(agents_searched.len(), 0); - - let profiles_searched: Vec = conductors[1] - .call(&bob_zome, "search_agents", String::from("سعيدة")) - .await; - - assert_eq!(profiles_searched.len(), 0); -} diff --git a/crates/coordinator/zome.nix b/crates/coordinator/zome.nix index 5e683878e..0898950a9 100644 --- a/crates/coordinator/zome.nix +++ b/crates/coordinator/zome.nix @@ -6,35 +6,6 @@ workspacePath = inputs.self.outPath; crateCargoToml = ./Cargo.toml; }; - - checks.profiles = inputs.hc-infra.outputs.builders.${system}.sweettest { - workspacePath = inputs.self.outPath; - dna = (inputs.hc-infra.outputs.builders.${system}.dna { - dnaManifest = builtins.toFile "dna.yaml" '' - --- - manifest_version: "1" - name: test_dna - integrity: - network_seed: ~ - properties: ~ - origin_time: 1709638576394039 - zomes: - - name: profiles_integrity - coordinator: - zomes: - - name: profiles - hash: ~ - dependencies: - - name: profiles_integrity - dylib: ~ - ''; - zomes = { - profiles = self'.packages.profiles; - profiles_integrity = self'.packages.profiles_integrity; - }; - }).meta.debug; - crateCargoToml = ./Cargo.toml; - }; }; } diff --git a/crates/integrity/Cargo.toml b/crates/integrity/Cargo.toml index 061cbf0c9..c31ec5e02 100644 --- a/crates/integrity/Cargo.toml +++ b/crates/integrity/Cargo.toml @@ -22,3 +22,4 @@ derive_more = "0" serde = "1" hdi = { workspace = true } +profiles_types = { path = "../types" } diff --git a/crates/integrity/src/agent_to_profile.rs b/crates/integrity/src/agent_to_profile.rs new file mode 100644 index 000000000..4a6d3f171 --- /dev/null +++ b/crates/integrity/src/agent_to_profile.rs @@ -0,0 +1,54 @@ +use hdi::prelude::*; +use profiles_types::validate_profile_for_agent_with_zome_index; + +pub fn validate_create_link_agent_to_profile( + action_hash: ActionHash, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + let _agent = base_address + .into_agent_pub_key() + .ok_or(wasm_error!(WasmErrorInner::Guest( + "No AgentPubKey associated with the base of an AgentToProfile link".to_string() + )))?; + // Check the entry type for the given action hash + let profile_hash = + target_address + .into_action_hash() + .ok_or(wasm_error!(WasmErrorInner::Guest( + "No action hash associated with link".to_string() + )))?; + let record = must_get_valid_record(profile_hash.clone())?; + let _profile: crate::Profile = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest( + "Linked action must reference an entry".to_string() + )))?; + + let result = validate_profile_for_agent_with_zome_index( + action.author.clone(), + action_hash, + profile_hash, + zome_info()?.id, + )?; + let ValidateCallbackResult::Valid = result else { + return Ok(result); + }; + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_agent_to_profile( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "AgentToProfile links cannot be updated", + ))) +} diff --git a/crates/integrity/src/lib.rs b/crates/integrity/src/lib.rs index 39ce556ea..2436355d2 100644 --- a/crates/integrity/src/lib.rs +++ b/crates/integrity/src/lib.rs @@ -7,20 +7,20 @@ //! //! Read about how to include both this zome and its frontend module in your application [here](https://holochain-open-dev.github.io/profiles). -use std::collections::BTreeMap; - use hdi::prelude::*; -/// Profile entry definition. -/// -/// The profile must include at a minimum the nickname of the agent -/// in order to be able to search for agents by nickname. -#[hdk_entry_helper] -#[derive(Clone)] -pub struct Profile { - pub nickname: String, - pub fields: BTreeMap, -} +pub use profiles_types::*; + +mod agent_to_profile; +mod path_to_profile; +mod prefix_path; +mod profile; +mod profile_claim; +use agent_to_profile::*; +use path_to_profile::*; +use prefix_path::*; +use profile::*; +use profile_claim::*; #[derive(Serialize, Deserialize)] #[serde(tag = "type")] @@ -28,12 +28,254 @@ pub struct Profile { #[unit_enum(UnitEntryTypes)] pub enum EntryTypes { Profile(Profile), + ProfileClaim(ProfileClaim), } #[derive(Serialize, Deserialize)] #[hdk_link_types] pub enum LinkTypes { PrefixPath, - PathToAgent, + PathToProfile, AgentToProfile, } + +#[hdk_extern] +pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_agent_joining( + _agent_pub_key: AgentPubKey, + _membrane_proof: &Option, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn action_hash(op: &Op) -> &ActionHash { + match op { + Op::StoreRecord(StoreRecord { record }) => record.action_address(), + Op::StoreEntry(StoreEntry { action, .. }) => &action.hashed.hash, + Op::RegisterUpdate(RegisterUpdate { update, .. }) => &update.hashed.hash, + Op::RegisterDelete(RegisterDelete { delete, .. }) => &delete.hashed.hash, + Op::RegisterAgentActivity(RegisterAgentActivity { action, .. }) => &action.hashed.hash, + Op::RegisterCreateLink(RegisterCreateLink { create_link }) => &create_link.hashed.hash, + Op::RegisterDeleteLink(RegisterDeleteLink { delete_link, .. }) => &delete_link.hashed.hash, + } +} +#[hdk_extern] +pub fn validate(op: Op) -> ExternResult { + match op.flattened::()? { + FlatOp::StoreEntry(store_entry) => match store_entry { + OpEntry::CreateEntry { app_entry, action } => match app_entry { + EntryTypes::Profile(profile) => { + validate_create_profile(EntryCreationAction::Create(action), profile) + } + EntryTypes::ProfileClaim(profile_claim) => validate_create_profile_claim( + EntryCreationAction::Create(action), + profile_claim, + ), + }, + OpEntry::UpdateEntry { + app_entry, action, .. + } => match app_entry { + EntryTypes::Profile(profile) => { + validate_create_profile(EntryCreationAction::Update(action), profile) + } + EntryTypes::ProfileClaim(profile_claim) => validate_create_profile_claim( + EntryCreationAction::Update(action), + profile_claim, + ), + }, + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterUpdate(update_entry) => match update_entry { + OpUpdate::Entry { app_entry, action } => match app_entry { + EntryTypes::Profile(profile) => { + validate_update_profile(action_hash(&op).clone(), action, profile) + } + EntryTypes::ProfileClaim(profile_claim) => { + validate_update_profile_claim(action, profile_claim) + } + }, + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterDelete(delete_entry) => validate_delete_profile(delete_entry.action), + FlatOp::RegisterCreateLink { + link_type, + base_address, + target_address, + tag, + action, + } => match link_type { + LinkTypes::AgentToProfile => validate_create_link_agent_to_profile( + action_hash(&op).clone(), + action, + base_address, + target_address, + tag, + ), + LinkTypes::PathToProfile => { + validate_create_link_path_to_profile(action, base_address, target_address, tag) + } + LinkTypes::PrefixPath => { + validate_create_link_prefix_path(action, base_address, target_address, tag) + } + }, + FlatOp::RegisterDeleteLink { + link_type, + base_address, + target_address, + tag, + original_action, + action, + } => match link_type { + LinkTypes::AgentToProfile => validate_delete_link_agent_to_profile( + action, + original_action, + base_address, + target_address, + tag, + ), + LinkTypes::PathToProfile => validate_delete_link_path_to_profile( + action, + original_action, + base_address, + target_address, + tag, + ), + LinkTypes::PrefixPath => validate_delete_link_prefix_path( + action, + original_action, + base_address, + target_address, + tag, + ), + }, + FlatOp::StoreRecord(store_record) => match store_record { + OpRecord::CreateEntry { app_entry, action } => match app_entry { + EntryTypes::Profile(profile) => { + validate_create_profile(EntryCreationAction::Create(action), profile) + } + EntryTypes::ProfileClaim(profile_claim) => validate_create_profile_claim( + EntryCreationAction::Create(action), + profile_claim, + ), + }, + OpRecord::UpdateEntry { + app_entry, action, .. + } => match app_entry { + EntryTypes::Profile(profile) => { + let result = validate_create_profile( + EntryCreationAction::Update(action.clone()), + profile.clone(), + )?; + let ValidateCallbackResult::Valid = result else { + return Ok(result); + }; + validate_update_profile(action_hash(&op).clone(), action, profile) + } + EntryTypes::ProfileClaim(profile_claim) => { + let result = validate_create_profile_claim( + EntryCreationAction::Update(action.clone()), + profile_claim.clone(), + )?; + let ValidateCallbackResult::Valid = result else { + return Ok(result); + }; + validate_update_profile_claim(action, profile_claim) + } + }, + OpRecord::DeleteEntry { action, .. } => validate_delete_profile(action), + OpRecord::CreateLink { + base_address, + target_address, + tag, + link_type, + action, + } => match link_type { + LinkTypes::AgentToProfile => validate_create_link_agent_to_profile( + action_hash(&op).clone(), + action, + base_address, + target_address, + tag, + ), + LinkTypes::PathToProfile => { + validate_create_link_path_to_profile(action, base_address, target_address, tag) + } + LinkTypes::PrefixPath => { + validate_create_link_prefix_path(action, base_address, target_address, tag) + } + }, + OpRecord::DeleteLink { + original_action_hash, + base_address, + action, + } => { + let record = must_get_valid_record(original_action_hash)?; + let create_link = match record.action() { + Action::CreateLink(create_link) => create_link.clone(), + _ => { + return Ok(ValidateCallbackResult::Invalid( + "The action that a DeleteLink deletes must be a CreateLink".to_string(), + )); + } + }; + let link_type = + match LinkTypes::from_type(create_link.zome_index, create_link.link_type)? { + Some(lt) => lt, + None => { + return Ok(ValidateCallbackResult::Valid); + } + }; + match link_type { + LinkTypes::AgentToProfile => validate_delete_link_agent_to_profile( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ), + LinkTypes::PathToProfile => validate_delete_link_path_to_profile( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ), + LinkTypes::PrefixPath => validate_delete_link_prefix_path( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ), + } + } + OpRecord::CreatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::Dna { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::OpenChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CloseChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::InitZomesComplete { .. } => Ok(ValidateCallbackResult::Valid), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterAgentActivity(agent_activity) => match agent_activity { + OpActivity::CreateAgent { agent, action } => { + let previous_action = must_get_action(action.prev_action)?; + match previous_action.action() { + Action::AgentValidationPkg(AgentValidationPkg { membrane_proof, .. }) => { + validate_agent_joining(agent, membrane_proof) + } + _ => Ok(ValidateCallbackResult::Invalid( + "The previous action for a `CreateAgent` action must be an `AgentValidationPkg`" + .to_string(), + )), + } + } + _ => Ok(ValidateCallbackResult::Valid), + }, + } +} diff --git a/crates/integrity/src/path_to_profile.rs b/crates/integrity/src/path_to_profile.rs new file mode 100644 index 000000000..2791a1785 --- /dev/null +++ b/crates/integrity/src/path_to_profile.rs @@ -0,0 +1,37 @@ +use hdi::prelude::*; + +pub fn validate_create_link_path_to_profile( + _action: CreateLink, + _base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // TODO: validate path base address? + + // Check the entry type for the given action hash + let action_hash = + target_address + .into_action_hash() + .ok_or(wasm_error!(WasmErrorInner::Guest( + "No action hash associated with link".to_string() + )))?; + let record = must_get_valid_record(action_hash)?; + let _notification: crate::Profile = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest( + "Linked action must reference an entry".to_string() + )))?; + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_path_to_profile( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // TODO: add the appropriate validation rules + Ok(ValidateCallbackResult::Valid) +} diff --git a/crates/integrity/src/prefix_path.rs b/crates/integrity/src/prefix_path.rs new file mode 100644 index 000000000..69524a1e2 --- /dev/null +++ b/crates/integrity/src/prefix_path.rs @@ -0,0 +1,21 @@ +use hdi::prelude::*; + +pub fn validate_create_link_prefix_path( + _action: CreateLink, + _base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // TODO: validate path base address? + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_prefix_path( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // TODO: add the appropriate validation rules + Ok(ValidateCallbackResult::Valid) +} diff --git a/crates/integrity/src/profile.rs b/crates/integrity/src/profile.rs new file mode 100644 index 000000000..4d420c412 --- /dev/null +++ b/crates/integrity/src/profile.rs @@ -0,0 +1,46 @@ +use hdi::prelude::*; +use profiles_types::{validate_profile_for_agent_with_zome_index, Profile}; + +pub fn validate_create_profile( + _action: EntryCreationAction, + profile: Profile, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} + +fn get_original_create_hash(update: &Update) -> ExternResult { + let previous_new_entry_action_hash = update.original_action_address.clone(); + + let record = must_get_valid_record(previous_new_entry_action_hash.clone())?; + + match record.action() { + Action::Create(_) => Ok(previous_new_entry_action_hash.clone()), + Action::Update(update) => get_original_create_hash(update), + _ => Err(wasm_error!(WasmErrorInner::Guest(format!("UNREACHABLE: an update action does not have a new entry action as its original_action_address")))) + } +} + +pub fn validate_update_profile( + action_hash: ActionHash, + action: Update, + _profile: Profile, +) -> ExternResult { + let original_create_hash = get_original_create_hash(&action)?; + + let result = validate_profile_for_agent_with_zome_index( + action.author.clone(), + action_hash, + original_create_hash, + zome_info()?.id, + )?; + let ValidateCallbackResult::Valid = result else { + return Ok(result); + }; + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_profile(_action: Delete) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "Profiles cannot be deleted", + ))) +} diff --git a/crates/integrity/src/profile_claim.rs b/crates/integrity/src/profile_claim.rs new file mode 100644 index 000000000..dd7e57c02 --- /dev/null +++ b/crates/integrity/src/profile_claim.rs @@ -0,0 +1,106 @@ +use hdi::prelude::*; +use profiles_types::ProfileClaim; + +use crate::{LinkTypes, UnitEntryTypes}; + +pub fn validate_create_profile_claim( + action: EntryCreationAction, + profile_claim: ProfileClaim, +) -> ExternResult { + let filter = ChainFilter::new(action.prev_action().clone()).include_cached_entries(); + let activity = must_get_agent_activity(action.author().clone(), filter)?; + + if let Some(_) = activity + .iter() + .find(|activity| activity.action.hashed.hash.eq(&profile_claim.profile_hash)) + { + // This is the agent that created the Profile + return Ok(ValidateCallbackResult::Invalid(format!( + "The author of the Profile can't create a ProfileClaim for that Profile" + ))); + } + + let profile_claim_entry_type: EntryType = UnitEntryTypes::ProfileClaim.try_into()?; + + let profile_claim_creates: Vec = activity + .iter() + .filter_map(|activity| match &activity.action.hashed.content { + Action::Create(create) => Some(create.clone()), + _ => None, + }) + .filter(|create| create.entry_type.eq(&profile_claim_entry_type)) + // TODO: filter here for RoleClaim entry type if more entry types are added to this zome + .collect(); + + if profile_claim_creates.len() > 1 { + return Ok(ValidateCallbackResult::Invalid(String::from( + "Only one ProfileClaim is allowed for a given source chain", + ))); + } + + // Get the CreateLink for the agent_to_profile_create_link_hash, and verify it's a link from the agent public key of the author to the ProfileClaim profile_hash + + let create_link_hash = profile_claim.agent_to_profile_create_link_hash; + + let record = must_get_valid_record(create_link_hash)?; + + let link_action = record.action().clone(); + + let Action::CreateLink(create_link) = link_action.clone() else { + return Ok(ValidateCallbackResult::Invalid(format!("The agent_to_profile_create_link_hash references a record that does not contain a CreateLink action"))); + }; + let Some(link_type) = LinkTypes::from_type(create_link.zome_index, create_link.link_type)? + else { + return Ok(ValidateCallbackResult::Invalid(format!( + "Invalid LinkType: not a profiles link type" + ))); + }; + + let LinkTypes::AgentToProfile = link_type else { + return Ok(ValidateCallbackResult::Invalid(format!( + "agent_to_profile_create_link_hash link is not of type AgentToProfile" + ))); + }; + + let base_address = create_link.base_address; + + let Some(agent) = base_address.into_agent_pub_key() else { + return Ok(ValidateCallbackResult::Invalid( + "No AgentPubKey associated with the base of the AgentToProfile link".to_string(), + )); + }; + + if agent.ne(action.author()) { + return Ok(ValidateCallbackResult::Invalid(format!( + "The author of the ProfileClaim is not the base for the AgentToProfile link" + ))); + } + + let Some(profile_hash) = create_link.target_address.into_action_hash() else { + return Ok(ValidateCallbackResult::Invalid( + "No ActionHash associated with the target of the AgentToProfile link".to_string(), + )); + }; + + if profile_hash.ne(&profile_claim.profile_hash) { + return Ok(ValidateCallbackResult::Invalid( + "The profile_hash in the ProfileClaim is not the target of the AgentToProfile link" + .to_string(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_update_profile_claim( + _action: Update, + _profile_claim: ProfileClaim, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "ProfileClaims cannot be updated", + ))) +} +pub fn validate_delete_profile_claim(_action: Delete) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "ProfileClaims cannot be deleted", + ))) +} diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml new file mode 100644 index 000000000..c77f21971 --- /dev/null +++ b/crates/types/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = [ + "guillem.cordoba@gmail.com", +] +edition = "2021" +name = "profiles_types" +version = "0.2.0" + +[dependencies] +derive_more = "0" +serde = "1" + +hdi = { workspace = true } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs new file mode 100644 index 000000000..8c9df7827 --- /dev/null +++ b/crates/types/src/lib.rs @@ -0,0 +1,112 @@ +use hdi::prelude::*; + +use std::collections::BTreeMap; + +/// Profile entry definition. +/// +/// The profile must include at a minimum the nickname of the agent +/// in order to be able to search for agents by nickname. +#[hdk_entry_helper] +#[derive(Clone)] +pub struct Profile { + pub nickname: String, + pub fields: BTreeMap, +} + +#[hdk_entry_helper] +#[derive(Clone)] +pub struct ProfileClaim { + pub profile_hash: ActionHash, + pub agent_to_profile_create_link_hash: ActionHash, +} + +pub const PROFILE_ENTRY_TYPE_INDEX: u8 = 0; +pub const PROFILE_CLAIM_ENTRY_TYPE_INDEX: u8 = 1; + +pub fn validate_profile_for_agent( + agent: AgentPubKey, + chain_top: ActionHash, + profile_hash: ActionHash, + profiles_integrity_zome_name: &ZomeName, +) -> ExternResult { + let dna_info = dna_info()?; + + let Some(profile_integrity_zome_index) = dna_info + .zome_names + .into_iter() + .position(|z| z.eq(&profiles_integrity_zome_name)) + else { + return Ok(ValidateCallbackResult::Invalid(String::from( + "Unreachable: there is no 'roles' integrity zome in this DNA", + ))); + }; + + validate_profile_for_agent_with_zome_index( + agent, + chain_top, + profile_hash, + ZomeIndex::new(profile_integrity_zome_index as u8), + ) +} + +pub fn validate_profile_for_agent_with_zome_index( + agent: AgentPubKey, + chain_top: ActionHash, + profile_hash: ActionHash, + profiles_integrity_zome_index: ZomeIndex, +) -> ExternResult { + let filter = ChainFilter::new(chain_top.clone()); + let activity = must_get_agent_activity(agent.clone(), filter)?; + + if let Some(_) = activity + .iter() + .find(|activity| activity.action.hashed.hash.eq(&profile_hash)) + { + // This is the agent that created the Profile + return Ok(ValidateCallbackResult::Valid); + } + + let profile_claim_creates: Vec = activity + .iter() + .filter_map(|activity| match &activity.action.hashed.content { + Action::Create(create) => Some(create.clone()), + _ => None, + }) + .filter(|create| { + let EntryType::App(app_entry_type) = &create.entry_type else { + return false; + }; + app_entry_type.zome_index() == profiles_integrity_zome_index + && app_entry_type.entry_index().0 == PROFILE_CLAIM_ENTRY_TYPE_INDEX + }) + .collect(); + + if profile_claim_creates.len() == 0 { + return Ok(ValidateCallbackResult::Invalid(String::from( + "No ProfileClaims were found for this agent", + ))); + } + + if profile_claim_creates.len() > 1 { + return Ok(ValidateCallbackResult::Invalid(String::from( + "Only one ProfileClaim is allowed for a given source chain", + ))); + } + + let profile_claim_create = profile_claim_creates[0].clone(); + let entry = must_get_entry(profile_claim_create.entry_hash)?; + + let Ok(profile_claim) = ProfileClaim::try_from(entry.content) else { + return Ok(ValidateCallbackResult::Invalid(String::from( + "Create action did not contain ProfileClaim entry type", + ))); + }; + + if profile_claim.profile_hash.ne(&profile_hash) { + return Ok(ValidateCallbackResult::Invalid(String::from( + "Agent's ProfileClaim is for a different profile than the given profile_hash", + ))); + } + + Ok(ValidateCallbackResult::Valid) +} diff --git a/flake.lock b/flake.lock index eeb75fd30..da48a52c0 100644 --- a/flake.lock +++ b/flake.lock @@ -4,7 +4,28 @@ "inputs": { "devshell": "devshell", "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs_5" + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1720988234, + "narHash": "sha256-OzqdY+tTyT6bPNi/jFt2lFmy3nLr7qyhm+0hd5QovgY=", + "owner": "tadfisher", + "repo": "android-nixpkgs", + "rev": "4aeeeec599210e54aee0ac31d4fcb512f87351a0", + "type": "github" + }, + "original": { + "owner": "tadfisher", + "repo": "android-nixpkgs", + "rev": "4aeeeec599210e54aee0ac31d4fcb512f87351a0", + "type": "github" + } + }, + "android-nixpkgs_2": { + "inputs": { + "devshell": "devshell_2", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_8" }, "locked": { "lastModified": 1720988234, @@ -67,6 +88,36 @@ } }, "crane_4": { + "locked": { + "lastModified": 1725125250, + "narHash": "sha256-CB20rDD5eHikF6mMTTJdwPP1qvyoiyyw1RDUzwIaIF8=", + "owner": "ipetkov", + "repo": "crane", + "rev": "96fd12c7100e9e05fa1a0a5bd108525600ce282f", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_5": { + "locked": { + "lastModified": 1725125250, + "narHash": "sha256-CB20rDD5eHikF6mMTTJdwPP1qvyoiyyw1RDUzwIaIF8=", + "owner": "ipetkov", + "repo": "crane", + "rev": "96fd12c7100e9e05fa1a0a5bd108525600ce282f", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_6": { "locked": { "lastModified": 1727974419, "narHash": "sha256-WD0//20h+2/yPGkO88d2nYbb23WMWYvnRyDQ9Dx4UHg=", @@ -81,7 +132,7 @@ "type": "github" } }, - "crane_5": { + "crane_7": { "locked": { "lastModified": 1725125250, "narHash": "sha256-CB20rDD5eHikF6mMTTJdwPP1qvyoiyyw1RDUzwIaIF8=", @@ -96,7 +147,7 @@ "type": "github" } }, - "crane_6": { + "crane_8": { "locked": { "lastModified": 1725125250, "narHash": "sha256-CB20rDD5eHikF6mMTTJdwPP1qvyoiyyw1RDUzwIaIF8=", @@ -112,6 +163,28 @@ } }, "devshell": { + "inputs": { + "nixpkgs": [ + "p2p-shipyard", + "android-nixpkgs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722113426, + "narHash": "sha256-Yo/3loq572A8Su6aY5GP56knpuKYRvM2a1meP9oJZCw=", + "owner": "numtide", + "repo": "devshell", + "rev": "67cce7359e4cd3c45296fb4aaf6a19e2a9c757ae", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "devshell_2": { "inputs": { "nixpkgs": [ "playground", @@ -193,11 +266,11 @@ "nixpkgs-lib": "nixpkgs-lib_4" }, "locked": { - "lastModified": 1727826117, - "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "lastModified": 1725234343, + "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6", "type": "github" }, "original": { @@ -228,6 +301,42 @@ "inputs": { "nixpkgs-lib": "nixpkgs-lib_6" }, + "locked": { + "lastModified": 1727826117, + "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_7": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_7" + }, + "locked": { + "lastModified": 1725234343, + "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_8": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_8" + }, "locked": { "lastModified": 1725234343, "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=", @@ -260,6 +369,24 @@ "type": "github" } }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "hc-infra": { "inputs": { "crane": [ @@ -297,19 +424,56 @@ "hc-infra_2": { "inputs": { "crane": [ - "playground", + "p2p-shipyard", "hc-infra", "holonix", "crane" ], "holonix": "holonix_3", "nixpkgs": [ - "playground", + "p2p-shipyard", "hc-infra", "holonix", "nixpkgs" ], "pnpmnixpkgs": "pnpmnixpkgs_2", + "rust-overlay": [ + "p2p-shipyard", + "hc-infra", + "holonix", + "rust-overlay" + ] + }, + "locked": { + "lastModified": 1727440365, + "narHash": "sha256-XeonUZzVKcl3QDrhE9zP2JuK4LkzSsNIf/p/qKS9PNM=", + "owner": "holochain-open-dev", + "repo": "infrastructure", + "rev": "80fae8556cdcc5b8dc155ca41f3786787bcf806a", + "type": "github" + }, + "original": { + "owner": "holochain-open-dev", + "repo": "infrastructure", + "type": "github" + } + }, + "hc-infra_3": { + "inputs": { + "crane": [ + "playground", + "hc-infra", + "holonix", + "crane" + ], + "holonix": "holonix_5", + "nixpkgs": [ + "playground", + "hc-infra", + "holonix", + "nixpkgs" + ], + "pnpmnixpkgs": "pnpmnixpkgs_3", "rust-overlay": [ "playground", "hc-infra", @@ -331,7 +495,7 @@ "type": "github" } }, - "hc-infra_3": { + "hc-infra_4": { "inputs": { "crane": [ "playground", @@ -340,7 +504,7 @@ "holonix", "crane" ], - "holonix": "holonix_5", + "holonix": "holonix_7", "nixpkgs": [ "playground", "p2p-shipyard", @@ -348,7 +512,7 @@ "holonix", "nixpkgs" ], - "pnpmnixpkgs": "pnpmnixpkgs_3", + "pnpmnixpkgs": "pnpmnixpkgs_4", "rust-overlay": [ "playground", "p2p-shipyard", @@ -473,6 +637,40 @@ "type": "github" } }, + "hc-launch_7": { + "flake": false, + "locked": { + "lastModified": 1717431387, + "narHash": "sha256-+VvWwBmxcgePV1L6kU2mSkg3emMiMgpdQnCqvQJkRPk=", + "owner": "holochain", + "repo": "hc-launch", + "rev": "9d9cab5e6b57e1c278113921ff203e515c8bbd2e", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "holochain-0.3", + "repo": "hc-launch", + "type": "github" + } + }, + "hc-launch_8": { + "flake": false, + "locked": { + "lastModified": 1717431387, + "narHash": "sha256-+VvWwBmxcgePV1L6kU2mSkg3emMiMgpdQnCqvQJkRPk=", + "owner": "holochain", + "repo": "hc-launch", + "rev": "9d9cab5e6b57e1c278113921ff203e515c8bbd2e", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "holochain-0.3", + "repo": "hc-launch", + "type": "github" + } + }, "hc-scaffold": { "flake": false, "locked": { @@ -508,6 +706,40 @@ } }, "hc-scaffold_3": { + "flake": false, + "locked": { + "lastModified": 1724073530, + "narHash": "sha256-PUM8otA5F5s8ZHxhjupn7R+RZAjh2rueYIFwu3UkK44=", + "owner": "holochain", + "repo": "scaffolding", + "rev": "8a6d1dab0f1668c2781a46d93a5ad638fcf25598", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "holochain-0.3", + "repo": "scaffolding", + "type": "github" + } + }, + "hc-scaffold_4": { + "flake": false, + "locked": { + "lastModified": 1724073530, + "narHash": "sha256-PUM8otA5F5s8ZHxhjupn7R+RZAjh2rueYIFwu3UkK44=", + "owner": "holochain", + "repo": "scaffolding", + "rev": "8a6d1dab0f1668c2781a46d93a5ad638fcf25598", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "holochain-0.3", + "repo": "scaffolding", + "type": "github" + } + }, + "hc-scaffold_5": { "flake": false, "locked": { "lastModified": 1727691892, @@ -524,7 +756,7 @@ "type": "github" } }, - "hc-scaffold_4": { + "hc-scaffold_6": { "flake": false, "locked": { "lastModified": 1727691892, @@ -541,7 +773,7 @@ "type": "github" } }, - "hc-scaffold_5": { + "hc-scaffold_7": { "flake": false, "locked": { "lastModified": 1724073530, @@ -558,7 +790,7 @@ "type": "github" } }, - "hc-scaffold_6": { + "hc-scaffold_8": { "flake": false, "locked": { "lastModified": 1724073530, @@ -629,16 +861,16 @@ "holochain_4": { "flake": false, "locked": { - "lastModified": 1728056814, - "narHash": "sha256-OUVNmUCUk4G2ur+O/Q6Ji77iHQeN3PufmiPDz9MS8AY=", + "lastModified": 1722347117, + "narHash": "sha256-Jv4DxaVtdbO+fOD4woFoepCCOtRN/HF94xJSwViz3ck=", "owner": "holochain", "repo": "holochain", - "rev": "63aeec5fd95b3263bc8ebce73c53b9f0e03bbf36", + "rev": "97d86050b177829b623461970db5c3b64fbd74c1", "type": "github" }, "original": { "owner": "holochain", - "ref": "holochain-0.3.3", + "ref": "holochain-0.3.2", "repo": "holochain", "type": "github" } @@ -663,22 +895,56 @@ "holochain_6": { "flake": false, "locked": { - "lastModified": 1722347117, - "narHash": "sha256-Jv4DxaVtdbO+fOD4woFoepCCOtRN/HF94xJSwViz3ck=", + "lastModified": 1728056814, + "narHash": "sha256-OUVNmUCUk4G2ur+O/Q6Ji77iHQeN3PufmiPDz9MS8AY=", "owner": "holochain", "repo": "holochain", - "rev": "97d86050b177829b623461970db5c3b64fbd74c1", + "rev": "63aeec5fd95b3263bc8ebce73c53b9f0e03bbf36", "type": "github" }, "original": { "owner": "holochain", - "ref": "holochain-0.3.2", + "ref": "holochain-0.3.3", "repo": "holochain", "type": "github" } }, - "holonix": { - "inputs": { + "holochain_7": { + "flake": false, + "locked": { + "lastModified": 1722347117, + "narHash": "sha256-Jv4DxaVtdbO+fOD4woFoepCCOtRN/HF94xJSwViz3ck=", + "owner": "holochain", + "repo": "holochain", + "rev": "97d86050b177829b623461970db5c3b64fbd74c1", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "holochain-0.3.2", + "repo": "holochain", + "type": "github" + } + }, + "holochain_8": { + "flake": false, + "locked": { + "lastModified": 1722347117, + "narHash": "sha256-Jv4DxaVtdbO+fOD4woFoepCCOtRN/HF94xJSwViz3ck=", + "owner": "holochain", + "repo": "holochain", + "rev": "97d86050b177829b623461970db5c3b64fbd74c1", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "holochain-0.3.2", + "repo": "holochain", + "type": "github" + } + }, + "holonix": { + "inputs": { "crane": "crane", "flake-parts": "flake-parts", "hc-launch": "hc-launch", @@ -737,15 +1003,15 @@ "hc-scaffold": "hc-scaffold_3", "holochain": "holochain_3", "lair-keystore": "lair-keystore_3", - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_4", "rust-overlay": "rust-overlay_3" }, "locked": { - "lastModified": 1727888522, - "narHash": "sha256-v7xvwPMeIUkYnPuMG+uypRu259t1HoSYBY+1zaq8jHs=", + "lastModified": 1727194089, + "narHash": "sha256-+KmoByZhktCuJHNqYiZYedvSwhjgzLev0F0NcKNHgMY=", "owner": "holochain", "repo": "holonix", - "rev": "9d3c4cf95e0224a953de9a290d055e494113e42b", + "rev": "0aeff9984ab60ea70df3812be605a5f455f0489b", "type": "github" }, "original": { @@ -763,15 +1029,15 @@ "hc-scaffold": "hc-scaffold_4", "holochain": "holochain_4", "lair-keystore": "lair-keystore_4", - "nixpkgs": "nixpkgs_4", + "nixpkgs": "nixpkgs_5", "rust-overlay": "rust-overlay_4" }, "locked": { - "lastModified": 1728321646, - "narHash": "sha256-Wi6LEXhmErD4P4wELAcLP5z/keH7EeYl6zpWQzXXvsk=", + "lastModified": 1727194089, + "narHash": "sha256-+KmoByZhktCuJHNqYiZYedvSwhjgzLev0F0NcKNHgMY=", "owner": "holochain", "repo": "holonix", - "rev": "a3252429407995fae1987be1a0391504f8e40269", + "rev": "0aeff9984ab60ea70df3812be605a5f455f0489b", "type": "github" }, "original": { @@ -793,11 +1059,11 @@ "rust-overlay": "rust-overlay_5" }, "locked": { - "lastModified": 1727194089, - "narHash": "sha256-+KmoByZhktCuJHNqYiZYedvSwhjgzLev0F0NcKNHgMY=", + "lastModified": 1727888522, + "narHash": "sha256-v7xvwPMeIUkYnPuMG+uypRu259t1HoSYBY+1zaq8jHs=", "owner": "holochain", "repo": "holonix", - "rev": "0aeff9984ab60ea70df3812be605a5f455f0489b", + "rev": "9d3c4cf95e0224a953de9a290d055e494113e42b", "type": "github" }, "original": { @@ -818,6 +1084,58 @@ "nixpkgs": "nixpkgs_7", "rust-overlay": "rust-overlay_6" }, + "locked": { + "lastModified": 1728321646, + "narHash": "sha256-Wi6LEXhmErD4P4wELAcLP5z/keH7EeYl6zpWQzXXvsk=", + "owner": "holochain", + "repo": "holonix", + "rev": "a3252429407995fae1987be1a0391504f8e40269", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "main-0.3", + "repo": "holonix", + "type": "github" + } + }, + "holonix_7": { + "inputs": { + "crane": "crane_7", + "flake-parts": "flake-parts_7", + "hc-launch": "hc-launch_7", + "hc-scaffold": "hc-scaffold_7", + "holochain": "holochain_7", + "lair-keystore": "lair-keystore_7", + "nixpkgs": "nixpkgs_9", + "rust-overlay": "rust-overlay_7" + }, + "locked": { + "lastModified": 1727194089, + "narHash": "sha256-+KmoByZhktCuJHNqYiZYedvSwhjgzLev0F0NcKNHgMY=", + "owner": "holochain", + "repo": "holonix", + "rev": "0aeff9984ab60ea70df3812be605a5f455f0489b", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "main-0.3", + "repo": "holonix", + "type": "github" + } + }, + "holonix_8": { + "inputs": { + "crane": "crane_8", + "flake-parts": "flake-parts_8", + "hc-launch": "hc-launch_8", + "hc-scaffold": "hc-scaffold_8", + "holochain": "holochain_8", + "lair-keystore": "lair-keystore_8", + "nixpkgs": "nixpkgs_10", + "rust-overlay": "rust-overlay_8" + }, "locked": { "lastModified": 1727194089, "narHash": "sha256-+KmoByZhktCuJHNqYiZYedvSwhjgzLev0F0NcKNHgMY=", @@ -935,6 +1253,40 @@ "type": "github" } }, + "lair-keystore_7": { + "flake": false, + "locked": { + "lastModified": 1717684904, + "narHash": "sha256-vcXt67Tl1qwVUkx8CBevdQocqZXUEeoXjaYw86ljsYo=", + "owner": "holochain", + "repo": "lair", + "rev": "6a84ed490fc7074d107e38bbb4a8d707e9b8e066", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "lair_keystore-v0.4.5", + "repo": "lair", + "type": "github" + } + }, + "lair-keystore_8": { + "flake": false, + "locked": { + "lastModified": 1717684904, + "narHash": "sha256-vcXt67Tl1qwVUkx8CBevdQocqZXUEeoXjaYw86ljsYo=", + "owner": "holochain", + "repo": "lair", + "rev": "6a84ed490fc7074d107e38bbb4a8d707e9b8e066", + "type": "github" + }, + "original": { + "owner": "holochain", + "ref": "lair_keystore-v0.4.5", + "repo": "lair", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1717179513, @@ -988,6 +1340,30 @@ } }, "nixpkgs-lib_4": { + "locked": { + "lastModified": 1725233747, + "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + } + }, + "nixpkgs-lib_5": { + "locked": { + "lastModified": 1725233747, + "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + } + }, + "nixpkgs-lib_6": { "locked": { "lastModified": 1727825735, "narHash": "sha256-0xHYkMkeLVQAMa7gvkddbPqpxph+hDzdu1XdGPJR+Os=", @@ -999,7 +1375,7 @@ "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" } }, - "nixpkgs-lib_5": { + "nixpkgs-lib_7": { "locked": { "lastModified": 1725233747, "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", @@ -1011,7 +1387,7 @@ "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" } }, - "nixpkgs-lib_6": { + "nixpkgs-lib_8": { "locked": { "lastModified": 1725233747, "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", @@ -1023,7 +1399,7 @@ "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" } }, - "nixpkgs_2": { + "nixpkgs_10": { "locked": { "lastModified": 1717179513, "narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=", @@ -1039,7 +1415,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_2": { "locked": { "lastModified": 1717179513, "narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=", @@ -1055,6 +1431,22 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1727634051, + "narHash": "sha256-S5kVU7U82LfpEukbn/ihcyNt2+EvG7Z5unsKW9H/yFA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "06cf0e1da4208d3766d898b7fdab6513366d45b9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_4": { "locked": { "lastModified": 1717179513, @@ -1073,16 +1465,16 @@ }, "nixpkgs_5": { "locked": { - "lastModified": 1727634051, - "narHash": "sha256-S5kVU7U82LfpEukbn/ihcyNt2+EvG7Z5unsKW9H/yFA=", - "owner": "NixOS", + "lastModified": 1717179513, + "narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "06cf0e1da4208d3766d898b7fdab6513366d45b9", + "rev": "63dacb46bf939521bdc93981b4cbb7ecb58427a0", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-unstable", + "owner": "nixos", + "ref": "24.05", "repo": "nixpkgs", "type": "github" } @@ -1119,17 +1511,86 @@ "type": "github" } }, + "nixpkgs_8": { + "locked": { + "lastModified": 1727634051, + "narHash": "sha256-S5kVU7U82LfpEukbn/ihcyNt2+EvG7Z5unsKW9H/yFA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "06cf0e1da4208d3766d898b7fdab6513366d45b9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1717179513, + "narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "63dacb46bf939521bdc93981b4cbb7ecb58427a0", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "24.05", + "repo": "nixpkgs", + "type": "github" + } + }, "p2p-shipyard": { "inputs": { "android-nixpkgs": "android-nixpkgs", + "crane": [ + "p2p-shipyard", + "holonix", + "crane" + ], + "hc-infra": "hc-infra_2", + "holonix": "holonix_4", + "nixpkgs": [ + "p2p-shipyard", + "hc-infra", + "nixpkgs" + ], + "rust-overlay": [ + "p2p-shipyard", + "holonix", + "rust-overlay" + ], + "webkitgtknixpkgs": "webkitgtknixpkgs" + }, + "locked": { + "lastModified": 1728913643, + "narHash": "sha256-wpMb1WpGtFIYPxSqHhTRyG1AycUXjTE1waiJr7OPWio=", + "owner": "darksoil-studio", + "repo": "p2p-shipyard", + "rev": "2b98a9022d027c839084ff6b1656205493719517", + "type": "github" + }, + "original": { + "owner": "darksoil-studio", + "ref": "develop", + "repo": "p2p-shipyard", + "type": "github" + } + }, + "p2p-shipyard_2": { + "inputs": { + "android-nixpkgs": "android-nixpkgs_2", "crane": [ "playground", "p2p-shipyard", "holonix", "crane" ], - "hc-infra": "hc-infra_3", - "holonix": "holonix_6", + "hc-infra": "hc-infra_4", + "holonix": "holonix_8", "nixpkgs": [ "playground", "p2p-shipyard", @@ -1142,7 +1603,7 @@ "holonix", "rust-overlay" ], - "webkitgtknixpkgs": "webkitgtknixpkgs" + "webkitgtknixpkgs": "webkitgtknixpkgs_2" }, "locked": { "lastModified": 1728285492, @@ -1160,14 +1621,14 @@ }, "playground": { "inputs": { - "hc-infra": "hc-infra_2", - "holonix": "holonix_4", + "hc-infra": "hc-infra_3", + "holonix": "holonix_6", "nixpkgs": [ "playground", "holonix", "nixpkgs" ], - "p2p-shipyard": "p2p-shipyard" + "p2p-shipyard": "p2p-shipyard_2" }, "locked": { "lastModified": 1728899168, @@ -1200,6 +1661,22 @@ } }, "pnpmnixpkgs_2": { + "locked": { + "lastModified": 1727264057, + "narHash": "sha256-KQPI8CTTnB9CrJ7LrmLC4VWbKZfljEPBXOFGZFRpxao=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "759537f06e6999e141588ff1c9be7f3a5c060106", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pnpmnixpkgs_3": { "locked": { "lastModified": 1727907660, "narHash": "sha256-QftbyPoieM5M50WKUMzQmWtBWib/ZJbHo7mhj5riQec=", @@ -1215,7 +1692,7 @@ "type": "github" } }, - "pnpmnixpkgs_3": { + "pnpmnixpkgs_4": { "locked": { "lastModified": 1727264057, "narHash": "sha256-KQPI8CTTnB9CrJ7LrmLC4VWbKZfljEPBXOFGZFRpxao=", @@ -1239,6 +1716,7 @@ "holonix", "nixpkgs" ], + "p2p-shipyard": "p2p-shipyard", "playground": "playground" } }, @@ -1288,7 +1766,7 @@ "rust-overlay_3": { "inputs": { "nixpkgs": [ - "playground", + "p2p-shipyard", "hc-infra", "holonix", "nixpkgs" @@ -1309,6 +1787,51 @@ } }, "rust-overlay_4": { + "inputs": { + "nixpkgs": [ + "p2p-shipyard", + "holonix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1725243956, + "narHash": "sha256-0A5ZP8uDCyBdYUzayZfy6JFdTefP79oZVAjyqA/yuSI=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "a10c8092d5f82622be79ed4dd12289f72011f850", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_5": { + "inputs": { + "nixpkgs": [ + "playground", + "hc-infra", + "holonix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1725243956, + "narHash": "sha256-0A5ZP8uDCyBdYUzayZfy6JFdTefP79oZVAjyqA/yuSI=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "a10c8092d5f82622be79ed4dd12289f72011f850", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_6": { "inputs": { "nixpkgs": [ "playground", @@ -1330,7 +1853,7 @@ "type": "github" } }, - "rust-overlay_5": { + "rust-overlay_7": { "inputs": { "nixpkgs": [ "playground", @@ -1354,7 +1877,7 @@ "type": "github" } }, - "rust-overlay_6": { + "rust-overlay_8": { "inputs": { "nixpkgs": [ "playground", @@ -1392,6 +1915,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "webkitgtknixpkgs": { "locked": { "lastModified": 1716358718, @@ -1407,6 +1945,22 @@ "rev": "3f316d2a50699a78afe5e77ca486ad553169061e", "type": "github" } + }, + "webkitgtknixpkgs_2": { + "locked": { + "lastModified": 1716358718, + "narHash": "sha256-NQbegJb2ZZnAqp2EJhWwTf6DrZXSpA6xZCEq+RGV1r0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "3f316d2a50699a78afe5e77ca486ad553169061e", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "3f316d2a50699a78afe5e77ca486ad553169061e", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 4a74267c1..8c6b70cd5 100644 --- a/flake.nix +++ b/flake.nix @@ -5,6 +5,7 @@ nixpkgs.follows = "holonix/nixpkgs"; holonix.url = "github:holochain/holonix/main-0.3"; hc-infra.url = "github:holochain-open-dev/infrastructure"; + p2p-shipyard.url = "github:darksoil-studio/p2p-shipyard/develop"; playground.url = "github:darksoil-studio/holochain-playground"; }; @@ -25,6 +26,7 @@ inputsFrom = [ inputs'.holonix.devShells.default ]; packages = with pkgs; [ nodejs_20 + inputs'.p2p-shipyard.packages.hc-pilot inputs'.playground.packages.hc-playground ]; }; diff --git a/package-lock.json b/package-lock.json index 5daf59146..3ade0ff35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,9 @@ ], "devDependencies": { "@eslint/js": "^8.0.0", - "@holochain-playground/cli": "^0.1.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "concurrently": "^6.2.1", + "concurrently-repeat": "^0.0.1", "eslint": "^8.0.0", "eslint-config-prettier": "^9.1.0", "new-port-cli": "^1.0.0", @@ -1316,9 +1316,9 @@ "link": true }, "node_modules/@holochain-open-dev/signals": { - "version": "0.300.6", - "resolved": "https://registry.npmjs.org/@holochain-open-dev/signals/-/signals-0.300.6.tgz", - "integrity": "sha512-59szV9r2JARGfxbYA59ft9+CdlhiL/BEPNBxsBv7KEqfBZsRJq7gJZlhbV6dvD+ks5yDNtrxCEcmqQP6JSbktw==", + "version": "0.300.8", + "resolved": "https://registry.npmjs.org/@holochain-open-dev/signals/-/signals-0.300.8.tgz", + "integrity": "sha512-FdqO1yCFVTclgiKforseH0LxxKdXj84OD0ANWzAZrRtvte1bjetPiH6mfqbx1Pu0duyAqUEayVIfw10akBSW2g==", "dependencies": { "@holochain-open-dev/utils": "^0.300.2", "@holochain/client": "^0.17.1", @@ -1341,15 +1341,6 @@ "sort-keys": "^5.0.0" } }, - "node_modules/@holochain-playground/cli": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@holochain-playground/cli/-/cli-0.1.1.tgz", - "integrity": "sha512-JbapAe+uBaec52rTePjdlP0mq3zQhJG/hrdbCd+eecZLA3cXWEGgISR5YwLtx6udN+0ghCDH4U6KILjPiwWZMg==", - "dev": true, - "bin": { - "holochain-playground": "dist/app.js" - } - }, "node_modules/@holochain/client": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/@holochain/client/-/client-0.17.1.tgz", @@ -3249,6 +3240,19 @@ "node": ">=10.0.0" } }, + "node_modules/concurrently-repeat": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concurrently-repeat/-/concurrently-repeat-0.0.1.tgz", + "integrity": "sha512-9UR6DJRsn1D8tGjK6L7BR2cTkfTQXRJRokoaC3KQgthRBEKHwXJzWXt3EQ3V9hjaURHYX5vAeEjt5aWhCpvSwQ==", + "dev": true, + "dependencies": { + "concurrently": "^6.3.0", + "yargs": "^16.2.0" + }, + "bin": { + "concurrently-repeat": "index.mjs" + } + }, "node_modules/concurrently/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9143,7 +9147,7 @@ "license": "MIT", "dependencies": { "@holochain-open-dev/elements": "^0.300.1", - "@holochain-open-dev/signals": "^0.300.6", + "@holochain-open-dev/signals": "^0.300.8", "@holochain-open-dev/utils": "^0.300.2", "@holochain/client": "^0.17.1", "@lit/context": "^1.0.1", diff --git a/package.json b/package.json index 4bcd7001c..df303adaa 100644 --- a/package.json +++ b/package.json @@ -4,26 +4,23 @@ "workspaces": ["ui", "tests", "docs"], "scripts": { "start": "AGENTS=2 npm run network", - "network": "hc s clean && npm run build:happ && BOOTSTRAP_PORT=$(port) SIGNAL_PORT=$(port) UI_PORT=8888 concurrently \"npm start -w ui\" \"npm run local-services\" \"npm run launch\" \"hc playground\"", - "test": "npm run build:happ && nix flake check -L && npm test -w tests", - "launch": "echo pass | WEBKIT_DISABLE_DMABUF_RENDERER=1 RUST_LOG=warn hc launch --piped -n $AGENTS workdir/profiles-test.happ --ui-port $UI_PORT network --bootstrap http://127.0.0.1:$BOOTSTRAP_PORT webrtc ws://127.0.0.1:$SIGNAL_PORT", - "local-services": "hc run-local-services --bootstrap-port $BOOTSTRAP_PORT --signal-port $SIGNAL_PORT", + "network": "hc s clean && npm run build:happ && UI_PORT=8888 concurrently \"npm start -w ui\" \"npm run launch\" \"hc playground\"", + "test": "npm run build:happ && npm test -w tests", + "launch": "concurrently-repeat \"RUST_LOG=warn hc pilot workdir/profiles-test.happ --ui-port $UI_PORT\" $AGENTS", "build:happ": "npm run build:zome && hc app pack workdir --recursive", - "build:zome": "CARGO_TARGET_DIR=target cargo build --release --target wasm32-unknown-unknown", - "docs:start": "npm run docs:setup && storybook dev -p 6006", - "docs:publish": "npm run docs:setup && storybook build && gh-pages -d ./storybook-static -b gh-pages", - "docs:setup": "npm run build -w @holochain-open-dev/profiles && npm run analyze -w @holochain-open-dev/profiles" + "build:zome": "CARGO_TARGET_DIR=target cargo build --release --target wasm32-unknown-unknown" }, "devDependencies": { - "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@eslint/js": "^8.0.0", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "concurrently": "^6.2.1", + "concurrently-repeat": "^0.0.1", "eslint": "^8.0.0", "eslint-config-prettier": "^9.1.0", "new-port-cli": "^1.0.0", "prettier": "^3.2.5", - "typescript-eslint": "^7.7.0", - "typescript": "^5.4.5" + "typescript": "^5.4.5", + "typescript-eslint": "^7.7.0" }, "type": "module" } diff --git a/stories/1-introduction.mdx b/stories/1-introduction.mdx deleted file mode 100644 index b7b94461a..000000000 --- a/stories/1-introduction.mdx +++ /dev/null @@ -1,27 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - - - -# @holochain-open-dev/profiles - -The profiles zome and its accompanying frontend module are designed to implement and export useful functionality around personal profile information about the agents in a Holochain DHT. - -The only field that this module assumes is the nickname, which it index the agents by. - -Existing functionalities: - -- Creating a profile. -- Updating a profile. -- Searching agents by nickname. -- Getting the profile for a list of agents. -- Configurable profile fields. -- Profile detail frontend element. - -> In the future, when the personas & profiles application is fully developed, this module will switch to storing data in it, and will serve only as a bridge to get that private data. We hope to maintain the modules and their interfaces as similar as they are now, and that the migration friction is low. - -This module follows the [holochain-open-dev](https://github.com/holochain-open-dev/) pattern of developing holochain modules. Read [its documentation](https://holochain-open-dev.github.io) to understand more about its motivation and the big picture. - -To integrate this module into your application: - -- If you are starting a new project from scratch, it is very recommended to follow the [Template Setup](?path=/docs/template-setup--docs). -- If not, you can visit [Setting up the Backend](?path=/docs/backend-setting-up-the-zomes--docs) and [Setting up the Frontend](?path=/docs/frontend-setting-up-the-frontend--docs). diff --git a/stories/2.1-backend-setup.mdx b/stories/2.1-backend-setup.mdx deleted file mode 100644 index 2296045a6..000000000 --- a/stories/2.1-backend-setup.mdx +++ /dev/null @@ -1,36 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - - - -# Setting up the zomes - -> It's much much easier to set up the backend by using the [holochain-open-dev template](https://github.com/holochain-open-dev/templates). Only follow this guide if you can't use the template. - -> This guide assumes you are inside a nix-shell environment with `hc scaffold` available. - -1. Scaffold a new zome pair named `profiles` with: - -```bash -hc scaffold zome profiles -``` - -Select the "Integrity/coordinator zome pair" option, and accept the path that the scaffolding tool offers to scaffold the zomes. - -2. Add the `hc_zome_profiles_coordinator` and `hc_zome_profiles_integrity` zomes as dependencies with: - -```bash -cargo add -p profiles hc_zome_profiles_coordinator -cargo add -p profiles_integrity hc_zome_profiles_integrity -``` - -3. Go into the newly scaffolded integrity zome's `lib.rs` (its path may be similar to `dnas/lobby/zomes/integrity/profiles/src/lib.rs`) and **replace its contents with**: - -```rust -extern crate hc_zome_profiles_integrity; -``` - -4. Go into the newly scaffolded coordinator zome's `lib.rs` (its path may be similar to `dnas/lobby/zomes/coordinator/profiles/src/lib.rs`) and **replace its contents with**: - -```rust -extern crate hc_zome_profiles_coordinator; -``` diff --git a/stories/2.2-integrity.mdx b/stories/2.2-integrity.mdx deleted file mode 100644 index 3aa136e57..000000000 --- a/stories/2.2-integrity.mdx +++ /dev/null @@ -1,11 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - - - -# hc_zome_profiles_integrity - -Use this crate directly if you want include and maybe extend this zome in your DNA. - -Notice that just by importing this crate, all its zome functions will be automatically defined in the consuming crate. This could create collisions in function names or entry definitions. - -[Read the documentation for the types available from this zome](https://docs.rs/hc_zome_profiles_integrity). diff --git a/stories/2.3-coordinator.mdx b/stories/2.3-coordinator.mdx deleted file mode 100644 index c237b0b7c..000000000 --- a/stories/2.3-coordinator.mdx +++ /dev/null @@ -1,11 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - - - -# hc_zome_profiles_coordinator - -Use this crate directly if you want include and maybe extend this zome in your DNA. - -Notice that just by importing this crate, all its zome functions will be automatically defined in the consuming crate. This could create collisions in function names or entry definitions. - -[Read the documentation for all the functions available from this zome.](https://docs.rs/hc_zome_profiles_coordinator) diff --git a/stories/3.1-frontend-setup.mdx b/stories/3.1-frontend-setup.mdx deleted file mode 100644 index 6ad5fd188..000000000 --- a/stories/3.1-frontend-setup.mdx +++ /dev/null @@ -1,125 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - - - -# Seting Up the Frontend - -> It's much much easier to set up the frontend by using the [holochain-open-dev template](https://github.com/holochain-open-dev/templates). Only follow this guide if you can't use the template. - -> This guide assumes you are building a web application written in JS or TS, using NPM as the package manager. - -> [Go here](https://holochain-open-dev.github.io/reusable-modules/frontend/frameworks/) to look at examples of integration of this module in different frontend frameworks (Vue, Svelte, etc.). - -1. Install this module and its necessary dependencies with: - -```bash -npm install @holochain-open-dev/profiles -``` - -Careful! If you are using NPM workspaces (which is the case for the apps generated with the holochain scaffolding tool (`hc scaffold`), you need to specify which workspace you want to install those dependencies to, and run the command from the root folder of the repository. In the case of the apps generated with the scaffolding tool: - -```bash -npm install @holochain-open-dev/profiles -w ui -``` - -2. Connect to Holochain with the `AppClient`, and create the `ProfilesStore` with it: - -```js -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; -import { AppWebsocket, AppWebsocket } from "@holochain/client"; - -async function setupProfilesStore() { - const client = await AppWebsocket.connect('', '') - -// TODO: change "MY_CELL_ROLE" for the roleId that you can find in your "happ.yaml" - const profilesStore = new ProfilesStore(new ProfilesClient(client, ''), { - avatarMode: "avatar-optional", - }); - return profilesStore; -} -``` - -3. Import the `` element and add it to your html **wrapping the whole section of your page in which you are going to be placing** the other elements from `@holochain-open-dev/profiles`: - -```js -// This can be placed in the index.js, at the top level of your web-app. -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -``` - -And then add the `` element in your html: - -```html - - - - -``` - -4. Attach the `profilesStore` to the `` element: - -- Go to [this page](https://holochain-open-dev.github.io/reusable-modules/frontend/frameworks/), select the framework you are using, and follow its example. - -You need to set the `store` property of it to your already instantiated `ProfilesStore` object: - -- If you **are using some JS framework**: - -```html - - - - - - - - - - - - - - -``` - -OR - -- If you **are not using any framework**: - -```js -const contextElement = document.querySelector("profiles-context"); -contextElement.store = store; -``` - -> You can read more about the context pattern [here](https://holochain-open-dev.github.io/reusable-modules/frontend/using/#context). - -5. [Choose which elements you need](?path=/docs/frontend-elements) and import them like this: - -```js -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -``` - -And then they are ready be used inside the `` just like any other HTML tag. - -This will define all the elements from this module in the global `CustomElementsRegistry`. You can read more about Custom Elements [here](https://developers.google.com/web/fundamentals/web-components/customelements). - -6. Add your preferred shoelace theme in your `` tag: - -```html - - - -``` - -or in JS: - -```js -import '@shoelace-style/shoelace/dist/themes/light.css'; -``` - -You can read more about how to initialize the shoelace theme [here](https://shoelace.style/getting-started/themes?id=activating-themes). - -That's it! You can spend some time now to take a look at [which elements are available for you to reuse](?path=/docs/frontend-elements-create-profile--docs). - -# Demo - -You can see a full working example of the UI working in [here](https://github.com/holochain-open-dev/profiles/blob/main/ui/demo/index.html). - diff --git a/stories/3.2-profiles-store.mdx b/stories/3.2-profiles-store.mdx deleted file mode 100644 index 30981407b..000000000 --- a/stories/3.2-profiles-store.mdx +++ /dev/null @@ -1,58 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; -import { ArgsTable } from '@storybook/addon-docs/blocks'; -import {ProfilesStore} from '@holochain-open-dev/profiles' - - - -# ProfilesStore - -The `ProfilesStore` is a typescript class that contains `svelte` stores, to which you can subscribe to get reactive updates in your elements. - -```js -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const config = { - avatarMode: "identicon", - - // Custom app level profile fields - additionalFields: [ - { - name: "location", - label: "Location", - required: true, - }, - { - name: "bio", - label: "Bio", - required: false, - } - ], -}; -const store = new ProfilesStore(new ProfilesClient(appClient, 'my-role-name'), config); -``` - -> Learn how to setup the `AppClient` object [here](https://www.npmjs.com/package/@holochain/client). - -The config for the `ProfilesStore` has these options: - -```ts -export interface ProfilesConfig { - avatarMode: "identicon" | "avatar-required" | "avatar-optional"; // default: 'avatar-optional' - additionalFields: FieldConfig[]; // default: [] - minNicknameLength: number; // default: 3 -} -``` - -The `FieldConfig` has these options: - -```ts -export interface FieldConfig { - name: string, - label: string, - required: boolean, -} -``` - -Learn more about the stores and how to integrate them in different frameworks [here](https://holochain-open-dev.github.io/reusable-modules/frontend/using/#stores). diff --git a/stories/agent-avatar.stories.js b/stories/agent-avatar.stories.js deleted file mode 100644 index 8fc6e8e1c..000000000 --- a/stories/agent-avatar.stories.js +++ /dev/null @@ -1,26 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/agent-avatar.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock(await demoProfiles()); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/agent-avatar", - tags: ["autodocs"], - component: "agent-avatar", - render: (args) => - html` - - `, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/stories/create-profile.stories.js b/stories/create-profile.stories.js deleted file mode 100644 index 8fa9c06fe..000000000 --- a/stories/create-profile.stories.js +++ /dev/null @@ -1,29 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/create-profile.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock( - await demoProfiles(), - decodeHashFromBase64("uhCAk8OKb2hznzG023xxh_vR3Q7Y4IEOAo4B0QN7ZhbGYeww") -); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/create-profile", - tags: ["autodocs"], - component: "create-profile", - render: (args) => - html` - - `, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/stories/list-profiles.stories.js b/stories/list-profiles.stories.js deleted file mode 100644 index dc30827bb..000000000 --- a/stories/list-profiles.stories.js +++ /dev/null @@ -1,26 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/list-profiles.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock(await demoProfiles()); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/list-profiles", - tags: ["autodocs"], - component: "list-profiles", - render: (args) => - html` - - `, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/stories/my-profile.stories.js b/stories/my-profile.stories.js deleted file mode 100644 index 0058781f3..000000000 --- a/stories/my-profile.stories.js +++ /dev/null @@ -1,31 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/my-profile.js"; -import "@holochain-open-dev/profiles/dist/elements/profile-prompt.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { decodeHashFromBase64 } from "@holochain/client"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock( - await demoProfiles(), - decodeHashFromBase64("uhCAk8OKb2hznzG023xxh_vR3Q7Y4IEOAo4B0QN7ZhbGYeww") -); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/my-profile", - tags: ["autodocs"], - component: "my-profile", - render: (args) => - html` - - `, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/stories/profile-detail.stories.js b/stories/profile-detail.stories.js deleted file mode 100644 index 1b0ae505f..000000000 --- a/stories/profile-detail.stories.js +++ /dev/null @@ -1,28 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/profile-detail.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock(await demoProfiles()); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/profile-detail", - tags: ["autodocs"], - component: "profile-detail", - render: (args) => - html` - - `, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/stories/profile-list-item-skeleton.stories.js b/stories/profile-list-item-skeleton.stories.js deleted file mode 100644 index ceb20a7ec..000000000 --- a/stories/profile-list-item-skeleton.stories.js +++ /dev/null @@ -1,18 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/profile-list-item-skeleton.js"; - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/profile-list-item-skeleton", - tags: ["autodocs"], - component: "profile-list-item-skeleton", - render: (args) => - html` - - - - `, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/stories/profile-prompt.stories.js b/stories/profile-prompt.stories.js deleted file mode 100644 index e868dfb95..000000000 --- a/stories/profile-prompt.stories.js +++ /dev/null @@ -1,41 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/profile-prompt.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock( - await demoProfiles(), - decodeHashFromBase64("uhCAk8OKb2hznzG023xxh_vR3Q7Y4IEOAo4B0QN7ZhbGYeww") -); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/profile-prompt", - tags: ["autodocs"], - component: "profile-prompt", - render: (args) => - html` - You have successfully created your profile! Now the application - elements should appear here. Click "Show code" to see how you can - include your elements.`, - argTypes: { - // backgroundColor: { control: 'color' }, - // onClick: { action: 'onClick' }, - // size: { - // control: { type: 'select' }, - // options: ['small', 'medium', 'large'], - // }, - }, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/stories/search-agent.stories.js b/stories/search-agent.stories.js deleted file mode 100644 index 96f96927d..000000000 --- a/stories/search-agent.stories.js +++ /dev/null @@ -1,48 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/search-agent.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock( - await demoProfiles(), - decodeHashFromBase64("uhCAk8OKb2hznzG023xxh_vR3Q7Y4IEOAo4B0QN7ZhbGYeww") -); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/search-agent", - tags: ["autodocs"], - component: "search-agent", - render: (args) => - html`
`, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; - -// export const Secondary = { -// args: { -// label: "Button", -// }, -// }; - -// export const Large = { -// args: { -// size: "large", -// label: "Button", -// }, -// }; - -// export const Small = { -// args: { -// size: "small", -// label: "Button", -// }, -// }; diff --git a/stories/template-setup.mdx b/stories/template-setup.mdx deleted file mode 100644 index 5c7292a97..000000000 --- a/stories/template-setup.mdx +++ /dev/null @@ -1,10 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - - - -# Template Setup - -If you are starting a new application from scratch, you can use the [holochain-open-dev template](https://github.com/holochain-open-dev/templates) to automatically get the profiles module for free in your application. - -Run `hc scaffold web-app --templates-url https://github.com/holochain-open-dev/templates` and follow all its instructions. - diff --git a/stories/update-profile.stories.js b/stories/update-profile.stories.js deleted file mode 100644 index e91b505d2..000000000 --- a/stories/update-profile.stories.js +++ /dev/null @@ -1,26 +0,0 @@ -import { html } from "lit-html"; -import "@holochain-open-dev/profiles/dist/elements/update-profile.js"; -import "@holochain-open-dev/profiles/dist/elements/profiles-context.js"; -import { - ProfilesZomeMock, - demoProfiles, -} from "@holochain-open-dev/profiles/dist/mocks.js"; -import { ProfilesStore, ProfilesClient } from "@holochain-open-dev/profiles"; - -const mock = new ProfilesZomeMock(await demoProfiles()); - -// More on how to set up stories at: https://storybook.js.org/docs/7.0/web-components/writing-stories/introduction -export default { - title: "Frontend/Elements/update-profile", - tags: ["autodocs"], - component: "update-profile", - render: (args) => - html` - - `, -}; - -// More on writing stories with args: https://storybook.js.org/docs/7.0/web-components/writing-stories/args -export const Demo = {}; diff --git a/tests/src/link-agent.test.ts b/tests/src/link-agent.test.ts new file mode 100644 index 000000000..2c53f0de6 --- /dev/null +++ b/tests/src/link-agent.test.ts @@ -0,0 +1,63 @@ +import { toPromise, watch } from '@holochain-open-dev/signals'; +import { EntryRecord } from '@holochain-open-dev/utils'; +import { dhtSync, pause, runScenario } from '@holochain/tryorama'; +import { assert, test } from 'vitest'; + +import { sampleProfile } from '../../ui/src/mocks.js'; +import { Profile } from '../../ui/src/types.js'; +import { setup } from './common.js'; + +test('create Profile and link agent', async () => { + await runScenario(async scenario => { + const { alice, bob } = await setup(scenario); + + let agentsWithProfile = await toPromise(alice.store.allProfiles); + assert.equal(agentsWithProfile.size, 0); + watch(alice.store.allProfiles, () => {}); // store keepalive + let myProfile = await toPromise(alice.store.myProfile); + watch(alice.store.myProfile, () => {}); // store keepalive + assert.notOk(myProfile); + + // Alice creates a Post + const profile: EntryRecord = + await alice.store.client.createProfile( + await sampleProfile(alice.store.client), + ); + assert.ok(profile); + + await pause(1000); // Difference in time between the create the processing of the signal + + agentsWithProfile = await toPromise(alice.store.allProfiles); + assert.equal(agentsWithProfile.size, 1); + + const aliceProfileStatus = alice.store.myProfile.get(); + assert.equal(aliceProfileStatus.status, 'completed'); + assert.ok((aliceProfileStatus as any).value); + + await alice.store.client.linkAgentWithMyProfile(bob.player.agentPubKey); + + agentsWithProfile = await toPromise(alice.store.allProfiles); + assert.equal(agentsWithProfile.size, 1); + + await pause(1000); // Difference in time between the create the processing of the signal + + const bobProfileStatus = alice.store.myProfile.get(); + assert.equal(bobProfileStatus.status, 'completed'); + assert.ok((bobProfileStatus as any).value); + + if (aliceProfileStatus.status !== 'completed' || !aliceProfileStatus.value) + return; + if (bobProfileStatus.status !== 'completed' || !bobProfileStatus.value) + return; + + const aliceLatestProfile = await toPromise( + aliceProfileStatus.value.latestVersion, + ); + + const bobLatestProfile = await toPromise( + bobProfileStatus.value.latestVersion, + ); + + assert.deepEqual(aliceLatestProfile, bobLatestProfile); + }); +}); diff --git a/tests/src/profile.test.ts b/tests/src/profile.test.ts index c26b0b54a..7dfb4c42d 100644 --- a/tests/src/profile.test.ts +++ b/tests/src/profile.test.ts @@ -11,27 +11,27 @@ test('create Profile', async () => { await runScenario(async scenario => { const { alice, bob } = await setup(scenario); - let agentsWithProfile = await toPromise(alice.store.agentsWithProfile); - assert.equal(agentsWithProfile.length, 0); - watch(alice.store.agentsWithProfile, () => {}); // store keepalive + let agentsWithProfile = await toPromise(alice.store.allProfiles); + assert.equal(agentsWithProfile.size, 0); + watch(alice.store.allProfiles, () => {}); // store keepalive let myProfile = await toPromise(alice.store.myProfile); watch(alice.store.myProfile, () => {}); // store keepalive assert.notOk(myProfile); - // Alice creates a Post - const profile: EntryRecord = - await alice.store.client.createProfile( - await sampleProfile(alice.store.client), - ); - assert.ok(profile); + // // Alice creates a Profile + // const profile: EntryRecord = + // await alice.store.client.createProfile( + // await sampleProfile(alice.store.client), + // ); + // assert.ok(profile); - await pause(1000); // Difference in time between the create the processing of the signal + // await pause(1000); // Difference in time between the create the processing of the signal - agentsWithProfile = await toPromise(alice.store.agentsWithProfile); - assert.equal(agentsWithProfile.length, 1); + // agentsWithProfile = await toPromise(alice.store.allProfiles); + // assert.equal(agentsWithProfile.size, 1); - const profileStatus = alice.store.myProfile.get(); - assert.equal(profileStatus.status, 'completed'); - assert.ok((profileStatus as any).value); + // const profileStatus = alice.store.myProfile.get(); + // assert.equal(profileStatus.status, 'completed'); + // assert.ok((profileStatus as any).value); }); }); diff --git a/tests/src/search.test.ts b/tests/src/search.test.ts new file mode 100644 index 000000000..827c075c0 --- /dev/null +++ b/tests/src/search.test.ts @@ -0,0 +1,37 @@ +import { toPromise, watch } from '@holochain-open-dev/signals'; +import { EntryRecord } from '@holochain-open-dev/utils'; +import { dhtSync, pause, runScenario } from '@holochain/tryorama'; +import { assert, test } from 'vitest'; + +import { sampleProfile } from '../../ui/src/mocks.js'; +import { Profile } from '../../ui/src/types.js'; +import { setup } from './common.js'; + +test('create Profile and search', async () => { + await runScenario(async scenario => { + const { alice, bob } = await setup(scenario); + + let agentsWithProfile = await toPromise(alice.store.allProfiles); + assert.equal(agentsWithProfile.size, 0); + watch(alice.store.allProfiles, () => {}); // store keepalive + let myProfile = await toPromise(alice.store.myProfile); + watch(alice.store.myProfile, () => {}); // store keepalive + assert.notOk(myProfile); + + // Alice creates a Post + const profile: EntryRecord = + await alice.store.client.createProfile( + await sampleProfile(alice.store.client, { + nickname: 'alice', + }), + ); + assert.ok(profile); + + await dhtSync([alice.player, bob.player], alice.player.cells[0].cell_id[0]); // Difference in time between the create the processing of the signal + + let profiles = await bob.store.client.searchProfiles('bob'); + assert.equal(profiles.length, 0); + profiles = await bob.store.client.searchProfiles('ali'); + assert.equal(profiles.length, 1); + }); +}); diff --git a/ui/package.json b/ui/package.json index 81295bbb2..1deec6406 100644 --- a/ui/package.json +++ b/ui/package.json @@ -28,7 +28,7 @@ }, "dependencies": { "@holochain-open-dev/elements": "^0.300.1", - "@holochain-open-dev/signals": "^0.300.6", + "@holochain-open-dev/signals": "^0.300.8", "@holochain-open-dev/utils": "^0.300.2", "@holochain/client": "^0.17.1", "@lit/context": "^1.0.1", diff --git a/ui/src/elements/agent-avatar.ts b/ui/src/elements/agent-avatar.ts index f6a1a8da4..b0828590a 100644 --- a/ui/src/elements/agent-avatar.ts +++ b/ui/src/elements/agent-avatar.ts @@ -1,162 +1,187 @@ -import { consume } from "@lit/context"; -import { hashProperty, sharedStyles } from "@holochain-open-dev/elements"; -import { css, html, LitElement } from "lit"; -import { property, customElement } from "lit/decorators.js"; -import { styleMap } from "lit/directives/style-map.js"; -import { AgentPubKey } from "@holochain/client"; -import { localized, msg } from "@lit/localize"; -import { EntryRecord } from "@holochain-open-dev/utils"; -import { SignalWatcher } from "@holochain-open-dev/signals"; - -import "@holochain-open-dev/elements/dist/elements/display-error.js"; -import "@holochain-open-dev/elements/dist/elements/holo-identicon.js"; -import "@shoelace-style/shoelace/dist/components/avatar/avatar.js"; -import "@shoelace-style/shoelace/dist/components/skeleton/skeleton.js"; -import "@shoelace-style/shoelace/dist/components/tooltip/tooltip.js"; - -import { profilesStoreContext } from "../context.js"; -import { ProfilesStore } from "../profiles-store.js"; -import { Profile } from "../types.js"; +import { hashProperty, sharedStyles } from '@holochain-open-dev/elements'; +import '@holochain-open-dev/elements/dist/elements/display-error.js'; +import '@holochain-open-dev/elements/dist/elements/holo-identicon.js'; +import { AsyncResult, SignalWatcher } from '@holochain-open-dev/signals'; +import { EntryRecord } from '@holochain-open-dev/utils'; +import { ActionHash, AgentPubKey } from '@holochain/client'; +import { consume } from '@lit/context'; +import { localized, msg } from '@lit/localize'; +import '@shoelace-style/shoelace/dist/components/avatar/avatar.js'; +import '@shoelace-style/shoelace/dist/components/skeleton/skeleton.js'; +import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js'; +import { LitElement, css, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { styleMap } from 'lit/directives/style-map.js'; + +import { profilesStoreContext } from '../context.js'; +import { ProfilesStore } from '../profiles-store.js'; +import { Profile } from '../types.js'; @localized() -@customElement("agent-avatar") +@customElement('agent-avatar') export class AgentAvatar extends SignalWatcher(LitElement) { - /** Public properties */ - - /** - * REQUIRED. The public key identifying the agent whose profile is going to be shown. - */ - @property(hashProperty("agent-pub-key")) - agentPubKey!: AgentPubKey; - - /** - * Size of the avatar image in pixels. - */ - @property({ type: Number }) - size = 32; - - /** - * Disables showing the tooltip for the public key - */ - @property({ type: Boolean, attribute: "disable-tooltip" }) - disableTooltip = false; - - /** - * Disable copying of the public key on click - */ - @property({ type: Boolean, attribute: "disable-copy" }) - disableCopy = false; - - /** Dependencies */ - - /** - * Profiles store for this element, not required if you embed this element inside a - */ - @consume({ context: profilesStoreContext, subscribe: true }) - @property() - store!: ProfilesStore; - - renderIdenticon() { - return html`
- - -
-
`; - } - - /** - * @internal - */ - timeout: any; - - renderProfile(profile: EntryRecord | undefined) { - if (!profile || !profile.entry.fields.avatar) return this.renderIdenticon(); - - const contents = html` -
- - this.dispatchEvent( - new CustomEvent("profile-clicked", { - composed: true, - bubbles: true, - detail: { - agentPubKey: this.agentPubKey, - }, - }) - )} - > - -
-
- `; - - return html` - - ${contents} - - `; - } - - render() { - if (this.store.config.avatarMode === "identicon") - return this.renderIdenticon(); - - const profile = this.store.profiles.get(this.agentPubKey).get(); - - switch (profile.status) { - case "pending": - return html``; - case "completed": - return this.renderProfile(profile.value); - case "error": - return html` - - `; - } - } - - static styles = [ - sharedStyles, - css` - .badge { - position: absolute; - right: 0; - bottom: 0; - } - `, - ]; + /** Public properties */ + + /** + * The public key identifying the agent whose profile is going to be shown. + */ + @property(hashProperty('agent-pub-key')) + agentPubKey: AgentPubKey | undefined; + + /** + * The profile hash to be shown + */ + @property(hashProperty('profile-hash')) + profileHash: ActionHash | undefined; + + /** + * Size of the avatar image in pixels. + */ + @property({ type: Number }) + size = 32; + + /** + * Disables showing the tooltip for the public key + */ + @property({ type: Boolean, attribute: 'disable-tooltip' }) + disableTooltip = false; + + /** + * Disable copying of the public key on click + */ + @property({ type: Boolean, attribute: 'disable-copy' }) + disableCopy = false; + + /** Dependencies */ + + /** + * Profiles store for this element, not required if you embed this element inside a + */ + @consume({ context: profilesStoreContext, subscribe: true }) + @property() + store!: ProfilesStore; + + renderIdenticon() { + return html`
+ + +
+
`; + } + + /** + * @internal + */ + timeout: any; + + renderProfile(profile: EntryRecord | undefined) { + if (!profile || !profile.entry.fields.avatar) return this.renderIdenticon(); + + const contents = html` +
+ + this.dispatchEvent( + new CustomEvent('profile-clicked', { + composed: true, + bubbles: true, + detail: { + agentPubKey: this.agentPubKey, + }, + }), + )} + > + +
+
+ `; + + return html` + + ${contents} + + `; + } + + profile(): AsyncResult | undefined> { + if (this.profileHash) { + return this.store.profiles.get(this.profileHash).latestVersion.get(); + } else if (this.agentPubKey) { + const agentProfile = this.store.agentProfile.get(this.agentPubKey).get(); + if (agentProfile.status !== 'completed') return agentProfile; + if (agentProfile.value === undefined) { + return { + status: 'completed', + value: undefined, + }; + } + return agentProfile.value.latestVersion.get(); + } else { + throw new Error( + 'Either agentPubKey or profileHash needs to be defined for the agent-avatar element', + ); + } + } + + render() { + if (this.store.config.avatarMode === 'identicon') + return this.renderIdenticon(); + + const profile = this.profile(); + + switch (profile.status) { + case 'pending': + return html``; + case 'completed': + return this.renderProfile(profile.value); + case 'error': + return html` + + `; + } + } + + static styles = [ + sharedStyles, + css` + .badge { + position: absolute; + right: 0; + bottom: 0; + } + `, + ]; } diff --git a/ui/src/elements/agent-mention.ts b/ui/src/elements/agent-mention.ts index a09a58b96..754cd3e74 100644 --- a/ui/src/elements/agent-mention.ts +++ b/ui/src/elements/agent-mention.ts @@ -1,116 +1,140 @@ -import { consume } from "@lit/context"; -import { hashProperty, sharedStyles } from "@holochain-open-dev/elements"; -import { css, html, LitElement } from "lit"; -import { property, customElement } from "lit/decorators.js"; -import { styleMap } from "lit/directives/style-map.js"; -import { AgentPubKey } from "@holochain/client"; -import { localized, msg } from "@lit/localize"; -import { EntryRecord } from "@holochain-open-dev/utils"; -import { SignalWatcher } from "@holochain-open-dev/signals"; +import { hashProperty, sharedStyles } from '@holochain-open-dev/elements'; +import '@holochain-open-dev/elements/dist/elements/display-error.js'; +import '@holochain-open-dev/elements/dist/elements/holo-identicon.js'; +import { AsyncResult, SignalWatcher } from '@holochain-open-dev/signals'; +import { EntryRecord } from '@holochain-open-dev/utils'; +import { ActionHash, AgentPubKey } from '@holochain/client'; +import { consume } from '@lit/context'; +import { localized, msg } from '@lit/localize'; +import '@shoelace-style/shoelace/dist/components/avatar/avatar.js'; +import '@shoelace-style/shoelace/dist/components/skeleton/skeleton.js'; +import '@shoelace-style/shoelace/dist/components/tag/tag.js'; +import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js'; +import { LitElement, css, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { styleMap } from 'lit/directives/style-map.js'; -import "@holochain-open-dev/elements/dist/elements/display-error.js"; -import "@holochain-open-dev/elements/dist/elements/holo-identicon.js"; -import "@shoelace-style/shoelace/dist/components/avatar/avatar.js"; -import "@shoelace-style/shoelace/dist/components/tag/tag.js"; -import "@shoelace-style/shoelace/dist/components/skeleton/skeleton.js"; -import "@shoelace-style/shoelace/dist/components/tooltip/tooltip.js"; - -import { profilesStoreContext } from "../context.js"; -import { ProfilesStore } from "../profiles-store.js"; -import { Profile } from "../types.js"; +import { profilesStoreContext } from '../context.js'; +import { ProfilesStore } from '../profiles-store.js'; +import { Profile } from '../types.js'; @localized() -@customElement("agent-mention") +@customElement('agent-mention') export class AgentMention extends SignalWatcher(LitElement) { - /** Public properties */ + /** Public properties */ + + /** + * The public key identifying the agent whose profile is going to be shown. + */ + @property(hashProperty('agent-pub-key')) + agentPubKey!: AgentPubKey; - /** - * REQUIRED. The public key identifying the agent whose profile is going to be shown. - */ - @property(hashProperty("agent-pub-key")) - agentPubKey!: AgentPubKey; + /** + * The profile hash to be shown + */ + @property(hashProperty('profile-hash')) + profileHash: ActionHash | undefined; - /** - * Size of the avatar image in pixels. - */ - @property({ type: Number }) - size = 24; + /** + * Size of the avatar image in pixels. + */ + @property({ type: Number }) + size = 24; - /** Dependencies */ + /** Dependencies */ - /** - * Profiles store for this element, not required if you embed this element inside a - */ - @consume({ context: profilesStoreContext, subscribe: true }) - @property() - store!: ProfilesStore; + /** + * Profiles store for this element, not required if you embed this element inside a + */ + @consume({ context: profilesStoreContext, subscribe: true }) + @property() + store!: ProfilesStore; - renderAvatar(profile: EntryRecord | undefined) { - if (!profile || !profile.entry.fields.avatar) { - return html`
- - -
`; - } - return html` - - - `; - } + renderAvatar(profile: EntryRecord | undefined) { + if (!profile || !profile.entry.fields.avatar) { + return html`
+ + +
`; + } + return html` + + + `; + } - renderProfile(profile: EntryRecord | undefined) { - return html` -
- ${this.renderAvatar(profile)} - ${profile?.entry.nickname} -
- `; - } + renderProfile(profile: EntryRecord | undefined) { + return html` +
+ ${this.renderAvatar(profile)} + ${profile?.entry.nickname} +
+ `; + } - renderContent() { - const profile = this.store.profiles.get(this.agentPubKey).get(); - switch (profile.status) { - case "pending": - return html``; - case "completed": - return this.renderProfile(profile.value); - case "error": - return html` - - `; - } - } + profile(): AsyncResult | undefined> { + if (this.profileHash) { + return this.store.profiles.get(this.profileHash).latestVersion.get(); + } else if (this.agentPubKey) { + const agentProfile = this.store.agentProfile.get(this.agentPubKey).get(); + if (agentProfile.status !== 'completed') return agentProfile; + if (agentProfile.value === undefined) { + return { + status: 'completed', + value: undefined, + }; + } + return agentProfile.value.latestVersion.get(); + } else { + throw new Error( + 'Either agentPubKey or profileHash needs to be defined for the agent-avatar element', + ); + } + } + renderContent() { + const profile = this.profile(); + switch (profile.status) { + case 'pending': + return html``; + case 'completed': + return this.renderProfile(profile.value); + case 'error': + return html` + + `; + } + } - render() { - return html` - ${this.renderContent()} - `; - } + render() { + return html` + ${this.renderContent()} + `; + } - static styles = [ - sharedStyles, - css` - :host { - display: inline-flex; - } - `, - ]; + static styles = [ + sharedStyles, + css` + :host { + display: inline-flex; + } + `, + ]; } diff --git a/ui/src/elements/agents-avatars.ts b/ui/src/elements/agents-avatars.ts index e820e346e..4bae3820b 100644 --- a/ui/src/elements/agents-avatars.ts +++ b/ui/src/elements/agents-avatars.ts @@ -1,41 +1,47 @@ -import { sharedStyles } from "@holochain-open-dev/elements"; -import { AgentPubKey } from "@holochain/client"; -import { localized } from "@lit/localize"; -import { LitElement, css, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { SignalWatcher } from "@holochain-open-dev/signals"; +import { sharedStyles } from '@holochain-open-dev/elements'; +import { SignalWatcher } from '@holochain-open-dev/signals'; +import { ActionHash, AgentPubKey } from '@holochain/client'; +import { localized } from '@lit/localize'; +import { LitElement, css, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; /** * @element agents-avatars */ @localized() -@customElement("agents-avatars") +@customElement('agents-avatars') export class AgentsAvatars extends SignalWatcher(LitElement) { - @property() - agents!: AgentPubKey[]; + @property() + agents: AgentPubKey[] = []; - render() { - return html` -
- ${this.agents - .slice(0, 3) - .map((a) => html``)} - ${this.agents.length > 3 - ? html`` - : html``} -
- `; - } + @property() + profilesHashes: ActionHash[] = []; - static styles = [ - css` - .avatar-group agent-avatar:not(:first-of-type) { - margin-left: -0.5rem; - } - `, - sharedStyles, - ]; + render() { + return html` +
+ ${this.agents + .slice(0, 3) + .map(a => html``)} + ${this.profilesHashes + .slice(0, 3 - this.agents.length) + .map(p => html``)} + ${this.agents.length + this.profilesHashes.length > 3 + ? html`` + : html``} +
+ `; + } + + static styles = [ + css` + .avatar-group agent-avatar:not(:first-of-type) { + margin-left: -0.5rem; + } + `, + sharedStyles, + ]; } diff --git a/ui/src/elements/list-profiles.ts b/ui/src/elements/all-profiles.ts similarity index 67% rename from ui/src/elements/list-profiles.ts rename to ui/src/elements/all-profiles.ts index 2332e4579..366786faa 100644 --- a/ui/src/elements/list-profiles.ts +++ b/ui/src/elements/all-profiles.ts @@ -1,8 +1,8 @@ import { sharedStyles } from '@holochain-open-dev/elements'; import '@holochain-open-dev/elements/dist/elements/display-error.js'; -import { SignalWatcher } from '@holochain-open-dev/signals'; -import { EntryRecord } from '@holochain-open-dev/utils'; -import { AgentPubKey } from '@holochain/client'; +import { SignalWatcher, joinAsyncMap } from '@holochain-open-dev/signals'; +import { EntryRecord, mapValues } from '@holochain-open-dev/utils'; +import { ActionHash, AgentPubKey } from '@holochain/client'; import { consume } from '@lit/context'; import { localized, msg } from '@lit/localize'; import { LitElement, css, html } from 'lit'; @@ -15,12 +15,12 @@ import './agent-avatar.js'; import './profile-list-item-skeleton.js'; /** - * @element list-profiles - * @fires agent-selected - Fired when the user selects an agent from the list. Detail will have this shape: { agentPubKey: } + * @element all-profiles + * @fires profile-selected - Fired when the user selects an agent from the list. Detail will have this shape: { profileHash: } */ @localized() -@customElement('list-profiles') -export class ListProfiles extends SignalWatcher(LitElement) { +@customElement('all-profiles') +export class AllProfiles extends SignalWatcher(LitElement) { /** * Profiles store for this element, not required if you embed this element inside a */ @@ -37,14 +37,14 @@ export class ListProfiles extends SignalWatcher(LitElement) { .join(''); } - fireAgentSelected(agentPubKey: AgentPubKey) { - if (agentPubKey) { + fireAgentSelected(profileHash: ActionHash) { + if (profileHash) { this.dispatchEvent( - new CustomEvent('agent-selected', { + new CustomEvent('profile-selected', { bubbles: true, composed: true, detail: { - agentPubKey, + profileHash, }, }), ); @@ -52,7 +52,7 @@ export class ListProfiles extends SignalWatcher(LitElement) { } renderList( - profiles: ReadonlyMap | undefined>, + profiles: ReadonlyMap | undefined>, ) { if (profiles.size === 0) return html`${msg('There are no created profiles yet')} >`; @@ -60,14 +60,14 @@ export class ListProfiles extends SignalWatcher(LitElement) { return html`
${Array.from(profiles.entries()).map( - ([agent_pub_key, profile]) => html` + ([profileHash, profile]) => html`
this.fireAgentSelected(agent_pub_key)} + .profileHash=${profileHash} + @click=${() => this.fireAgentSelected(profileHash)} > ${profile?.entry.nickname} @@ -78,8 +78,18 @@ export class ListProfiles extends SignalWatcher(LitElement) { `; } - render() { + allProfiles() { const allProfiles = this.store.allProfiles.get(); + if (allProfiles.status !== 'completed') return allProfiles; + + const latestProfiles = joinAsyncMap( + mapValues(allProfiles.value, p => p.latestVersion.get()), + ); + return latestProfiles; + } + + render() { + const allProfiles = this.allProfiles(); switch (allProfiles.status) { case 'pending': diff --git a/ui/src/elements/my-profile.ts b/ui/src/elements/my-profile.ts index 8b79369c5..2590db020 100644 --- a/ui/src/elements/my-profile.ts +++ b/ui/src/elements/my-profile.ts @@ -1,55 +1,53 @@ -import { consume } from "@lit/context"; -import { html, LitElement } from "lit"; -import { property, state, customElement } from "lit/decorators.js"; -import { sharedStyles, wrapPathInSvg } from "@holochain-open-dev/elements"; -import { SignalWatcher } from "@holochain-open-dev/signals"; -import { mdiPencil } from "@mdi/js"; - -import "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js"; - -import { profilesStoreContext } from "../context.js"; -import { ProfilesStore } from "../profiles-store.js"; - -import "./update-profile.js"; -import "./profile-detail.js"; +import { sharedStyles, wrapPathInSvg } from '@holochain-open-dev/elements'; +import { SignalWatcher } from '@holochain-open-dev/signals'; +import { consume } from '@lit/context'; +import { mdiPencil } from '@mdi/js'; +import '@shoelace-style/shoelace/dist/components/icon-button/icon-button.js'; +import { LitElement, html } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; + +import { profilesStoreContext } from '../context.js'; +import { ProfilesStore } from '../profiles-store.js'; +import './profile-detail.js'; +import './update-profile.js'; /** * @element my-profile */ -@customElement("my-profile") +@customElement('my-profile') export class MyProfile extends SignalWatcher(LitElement) { - /** - * Profiles store for this element, not required if you embed this element inside a - */ - @consume({ context: profilesStoreContext, subscribe: true }) - @property() - store!: ProfilesStore; - - /** Private properties */ - - /** - * @internal - */ - @state() - private _editing = false; - - render() { - if (this._editing) - return html` (this._editing = false)} - @cancel-edit-profile=${() => (this._editing = false)} - >`; - - return html` - - (this._editing = true)} - > - - `; - } - - static styles = [sharedStyles]; + /** + * Profiles store for this element, not required if you embed this element inside a + */ + @consume({ context: profilesStoreContext, subscribe: true }) + @property() + store!: ProfilesStore; + + /** Private properties */ + + /** + * @internal + */ + @state() + private _editing = false; + + render() { + if (this._editing) + return html` (this._editing = false)} + @cancel-edit-profile=${() => (this._editing = false)} + >`; + + return html` + + (this._editing = true)} + > + + `; + } + + static styles = [sharedStyles]; } diff --git a/ui/src/elements/profile-detail.ts b/ui/src/elements/profile-detail.ts index a938a37ce..0ffa95aad 100644 --- a/ui/src/elements/profile-detail.ts +++ b/ui/src/elements/profile-detail.ts @@ -1,139 +1,167 @@ -import { consume } from "@lit/context"; -import { AgentPubKey } from "@holochain/client"; -import { html, LitElement } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { localized, msg } from "@lit/localize"; -import { hashProperty, sharedStyles } from "@holochain-open-dev/elements"; -import { SignalWatcher } from "@holochain-open-dev/signals"; - -import "@holochain-open-dev/elements/dist/elements/display-error.js"; -import "@shoelace-style/shoelace/dist/components/skeleton/skeleton.js"; -import "./agent-avatar.js"; - -import { profilesStoreContext } from "../context.js"; -import { ProfilesStore } from "../profiles-store.js"; -import { Profile } from "../types.js"; -import { EntryRecord } from "@holochain-open-dev/utils"; +import { hashProperty, sharedStyles } from '@holochain-open-dev/elements'; +import '@holochain-open-dev/elements/dist/elements/display-error.js'; +import { AsyncResult, SignalWatcher } from '@holochain-open-dev/signals'; +import { EntryRecord } from '@holochain-open-dev/utils'; +import { ActionHash, AgentPubKey } from '@holochain/client'; +import { consume } from '@lit/context'; +import { localized, msg } from '@lit/localize'; +import '@shoelace-style/shoelace/dist/components/skeleton/skeleton.js'; +import { LitElement, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +import { profilesStoreContext } from '../context.js'; +import { ProfilesStore } from '../profiles-store.js'; +import { Profile } from '../types.js'; +import './agent-avatar.js'; /** * @element profile-detail */ @localized() -@customElement("profile-detail") +@customElement('profile-detail') export class ProfileDetail extends SignalWatcher(LitElement) { - /** Public properties */ - - /** - * REQUIRED. Public key identifying the agent for which the profile should be shown - */ - @property(hashProperty("agent-pub-key")) - agentPubKey!: AgentPubKey; - - /** - * Profiles store for this element, not required if you embed this element inside a - */ - @consume({ context: profilesStoreContext, subscribe: true }) - @property() - store!: ProfilesStore; - - /** Private properties */ - - getAdditionalFields(profile: Profile): Record { - const fields: Record = {}; - - for (const [key, value] of Object.entries(profile.fields)) { - if (key !== "avatar") { - fields[key] = value; - } - } - - return fields; - } - - renderAdditionalField(fieldId: string, fieldValue: string) { - return html` -
- - ${fieldId.substring(0, 1).toUpperCase()}${fieldId.substring( - 1 - )} - ${fieldValue} -
- `; - } - - renderProfile(profile: EntryRecord | undefined) { - if (!profile) - return html`
- ${msg("This agent hasn't created a profile yet")} -
`; - - return html` -
-
- - ${profile.entry.nickname} - - - - -
- - ${Object.entries(this.getAdditionalFields(profile.entry)) - .filter(([, value]) => value !== "") - .map(([key, value]) => this.renderAdditionalField(key, value))} -
- `; - } - - render() { - const profile = this.store.profiles.get(this.agentPubKey).get(); - switch (profile.status) { - case "pending": - return html` -
-
- -
- -
-
- - ${this.store.config.additionalFields.map( - () => html` - - ` - )} -
- `; - case "completed": - return this.renderProfile(profile.value); - case "error": - return html``; - } - } - - static styles = [sharedStyles]; + /** Public properties */ + + /** + * Public key identifying the agent for which the profile should be shown + */ + @property(hashProperty('agent-pub-key')) + agentPubKey!: AgentPubKey; + + /** + * The public key of the agent to render the profile for + */ + @property(hashProperty('profile-hash')) + profileHash: ActionHash | undefined; + + /** + * Profiles store for this element, not required if you embed this element inside a + */ + @consume({ context: profilesStoreContext, subscribe: true }) + @property() + store!: ProfilesStore; + + /** Private properties */ + + getAdditionalFields(profile: Profile): Record { + const fields: Record = {}; + + for (const [key, value] of Object.entries(profile.fields)) { + if (key !== 'avatar') { + fields[key] = value; + } + } + + return fields; + } + + profile(): AsyncResult | undefined> { + if (this.profileHash) { + return this.store.profiles.get(this.profileHash).latestVersion.get(); + } else if (this.agentPubKey) { + const agentProfile = this.store.agentProfile.get(this.agentPubKey).get(); + if (agentProfile.status !== 'completed') return agentProfile; + if (agentProfile.value === undefined) { + return { + status: 'completed', + value: undefined, + }; + } + return agentProfile.value.latestVersion.get(); + } else { + throw new Error( + 'Either agentPubKey or profileHash needs to be defined for the agent-avatar element', + ); + } + } + + renderAdditionalField(fieldId: string, fieldValue: string) { + return html` +
+ + ${fieldId.substring(0, 1).toUpperCase()}${fieldId.substring( + 1, + )} + ${fieldValue} +
+ `; + } + + renderProfile(profile: EntryRecord | undefined) { + if (!profile) + return html`
+ ${msg("This agent hasn't created a profile yet")} +
`; + + return html` +
+
+ + ${profile.entry.nickname} + + + + +
+ + ${Object.entries(this.getAdditionalFields(profile.entry)) + .filter(([, value]) => value !== '') + .map(([key, value]) => this.renderAdditionalField(key, value))} +
+ `; + } + + render() { + const profile = this.profile(); + switch (profile.status) { + case 'pending': + return html` +
+
+ +
+ +
+
+ + ${this.store.config.additionalFields.map( + () => html` + + `, + )} +
+ `; + case 'completed': + return this.renderProfile(profile.value); + case 'error': + return html``; + } + } + + static styles = [sharedStyles]; } diff --git a/ui/src/elements/profile-list-item.ts b/ui/src/elements/profile-list-item.ts index 222218a47..b30aa5e37 100644 --- a/ui/src/elements/profile-list-item.ts +++ b/ui/src/elements/profile-list-item.ts @@ -1,55 +1,86 @@ -import { hashProperty, sharedStyles } from "@holochain-open-dev/elements"; -import { AgentPubKey } from "@holochain/client"; -import { consume } from "@lit/context"; -import { LitElement, html } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { localized, msg } from "@lit/localize"; -import { SignalWatcher } from "@holochain-open-dev/signals"; +import { hashProperty, sharedStyles } from '@holochain-open-dev/elements'; +import { AsyncResult, SignalWatcher } from '@holochain-open-dev/signals'; +import { EntryRecord } from '@holochain-open-dev/utils'; +import { ActionHash, AgentPubKey } from '@holochain/client'; +import { consume } from '@lit/context'; +import { localized, msg } from '@lit/localize'; +import { LitElement, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; -import "./agent-avatar.js"; -import "./profile-list-item-skeleton.js"; -import { profilesStoreContext } from "../context.js"; -import { ProfilesStore } from "../profiles-store.js"; +import { profilesStoreContext } from '../context.js'; +import { ProfilesStore } from '../profiles-store.js'; +import { Profile } from '../types.js'; +import './agent-avatar.js'; +import './profile-list-item-skeleton.js'; /** * @element profile-list-item */ @localized() -@customElement("profile-list-item") +@customElement('profile-list-item') export class ProfileListItem extends SignalWatcher(LitElement) { - /** - * REQUIRED: the public key of the agent to render the profile for - */ - @property(hashProperty("agent-pub-key")) - agentPubKey!: AgentPubKey; + /** + * The public key of the agent to render the profile for + */ + @property(hashProperty('agent-pub-key')) + agentPubKey: AgentPubKey | undefined; - /** - * Profiles store for this element, not required if you embed this element inside a - */ - @consume({ context: profilesStoreContext, subscribe: true }) - @property() - store!: ProfilesStore; + /** + * The public key of the agent to render the profile for + */ + @property(hashProperty('profile-hash')) + profileHash: ActionHash | undefined; - render() { - const profile = this.store.profiles.get(this.agentPubKey).get(); - switch (profile.status) { - case "pending": - return html``; - case "completed": - return html` -
- - ${profile.value?.entry.nickname} -
- `; - case "error": - return html``; - } - } + /** + * Profiles store for this element, not required if you embed this element inside a + */ + @consume({ context: profilesStoreContext, subscribe: true }) + @property() + store!: ProfilesStore; - static styles = [sharedStyles]; + profile(): AsyncResult | undefined> { + if (this.profileHash) { + return this.store.profiles.get(this.profileHash).latestVersion.get(); + } else if (this.agentPubKey) { + const agentProfile = this.store.agentProfile.get(this.agentPubKey).get(); + if (agentProfile.status !== 'completed') return agentProfile; + if (agentProfile.value === undefined) { + return { + status: 'completed', + value: undefined, + }; + } + return agentProfile.value.latestVersion.get(); + } else { + throw new Error( + 'Either agentPubKey or profileHash needs to be defined for the agent-avatar element', + ); + } + } + + render() { + const profile = this.profile(); + switch (profile.status) { + case 'pending': + return html``; + case 'completed': + return html` +
+ + ${profile.value?.entry.nickname} +
+ `; + case 'error': + return html``; + } + } + + static styles = [sharedStyles]; } diff --git a/ui/src/elements/profile-prompt.ts b/ui/src/elements/profile-prompt.ts index ad0cc1d3b..f3c7a6785 100644 --- a/ui/src/elements/profile-prompt.ts +++ b/ui/src/elements/profile-prompt.ts @@ -29,8 +29,8 @@ export class ProfilePrompt extends SignalWatcher(LitElement) { /** Private properties */ - private renderPrompt(myProfile: EntryRecord | undefined) { - if (myProfile) return html``; + private renderPrompt(myProfileExists: boolean) { + if (myProfileExists) return html``; return html`
`; case 'completed': - return this.renderPrompt(myProfile.value); + return this.renderPrompt(myProfile.value !== undefined); } } diff --git a/ui/src/elements/search-agent-dropdown.ts b/ui/src/elements/search-profile-dropdown.ts similarity index 72% rename from ui/src/elements/search-agent-dropdown.ts rename to ui/src/elements/search-profile-dropdown.ts index df5895622..bb240cf31 100644 --- a/ui/src/elements/search-agent-dropdown.ts +++ b/ui/src/elements/search-profile-dropdown.ts @@ -15,6 +15,7 @@ import { slice, } from '@holochain-open-dev/utils'; import { + ActionHash, AgentPubKey, decodeHashFromBase64, encodeHashToBase64, @@ -37,12 +38,12 @@ import './agent-avatar.js'; import './profile-list-item-skeleton.js'; /** - * @element search-agent-dropdown - * @fires agent-selected - Fired when the user selects some agent. Detail will have this shape: { agentPubKey: HoloHash } + * @element search-profile-dropdown + * @fires profile-selected - Fired when the user selects some agent. Detail will have this shape: { profileHash: ActionHash } */ @localized() -@customElement('search-agent-dropdown') -export class SearchAgentDropdown extends SignalWatcher(LitElement) { +@customElement('search-profile-dropdown') +export class SearchProfileDropdown extends SignalWatcher(LitElement) { /** Public attributes */ set searchFilter(sf: string | undefined) { @@ -65,20 +66,20 @@ export class SearchAgentDropdown extends SignalWatcher(LitElement) { store!: ProfilesStore; /** - * Agents that won't be listed in the search + * Profiles that won't be listed in the search */ @property() - excludedAgents: AgentPubKey[] = []; + excludedProfiles: ActionHash[] = []; /** * @internal */ _searchProfiles = pipe( this._searchFilter, - filter => this.store.client.searchAgents(filter!), - agents => { - const profiles = slice(this.store.profiles, agents); - return joinAsyncMap(mapValues(profiles, p => p.get())); + filter => this.store.client.searchProfiles(filter!), + profilesHashes => { + const profiles = slice(this.store.profiles, profilesHashes); + return joinAsyncMap(mapValues(profiles, p => p.latestVersion.get())); }, ); @@ -88,13 +89,11 @@ export class SearchAgentDropdown extends SignalWatcher(LitElement) { @query('#dropdown') public dropdown!: SlDropdown; - async onUsernameSelected(agentPubKey: AgentPubKey) { - const profile = await toPromise(this.store.profiles.get(agentPubKey)); + async onProfileSelected(profileHash: ActionHash) { this.dispatchEvent( - new CustomEvent('agent-selected', { + new CustomEvent('profile-selected', { detail: { - agentPubKey, - profile, + profileHash, }, bubbles: true, composed: true, @@ -102,7 +101,7 @@ export class SearchAgentDropdown extends SignalWatcher(LitElement) { ); } - renderAgentList() { + renderProfileList() { const sf = this._searchFilter.get(); if (!sf || sf.length < 3) return html` `; case 'completed': { - let agents = Array.from(searchResult.value.entries()); - let excludedStr = this.excludedAgents.map(a => a.toString()); + let profiles = Array.from(searchResult.value.entries()); + let excludedStr = this.excludedProfiles.map(a => a.toString()); - agents = agents.filter( - ([pubkey, _profile]) => !excludedStr.includes(pubkey.toString()), + profiles = profiles.filter( + ([profileHash, _profile]) => + !excludedStr.includes(profileHash.toString()), ); - if (agents.length === 0) + if (profiles.length === 0) return html` - ${msg('No agents match the filter')} + ${msg('No nicknames match the filter')} `; return html` - ${agents.map( - ([pubkey, profile]) => html` - + ${profiles.map( + ([profileHash, profile]) => html` + ${profile?.entry.nickname} @@ -174,10 +174,10 @@ export class SearchAgentDropdown extends SignalWatcher(LitElement) { { - this.onUsernameSelected(decodeHashFromBase64(e.detail.item.value)); + this.onProfileSelected(decodeHashFromBase64(e.detail.item.value)); }} > - ${this.renderAgentList()} + ${this.renderProfileList()} `; diff --git a/ui/src/elements/search-agent.ts b/ui/src/elements/search-profile.ts similarity index 78% rename from ui/src/elements/search-agent.ts rename to ui/src/elements/search-profile.ts index 0c0fa5bdb..ea27361c6 100644 --- a/ui/src/elements/search-agent.ts +++ b/ui/src/elements/search-profile.ts @@ -5,9 +5,9 @@ import { sharedStyles, } from '@holochain-open-dev/elements'; import '@holochain-open-dev/elements/dist/elements/display-error.js'; -import { SignalWatcher } from '@holochain-open-dev/signals'; +import { SignalWatcher, toPromise } from '@holochain-open-dev/signals'; import { EntryRecord } from '@holochain-open-dev/utils'; -import { AgentPubKey } from '@holochain/client'; +import { ActionHash, AgentPubKey } from '@holochain/client'; import { consume } from '@lit/context'; import { localized, msg } from '@lit/localize'; import '@shoelace-style/shoelace/dist/components/dropdown/dropdown.js'; @@ -21,17 +21,16 @@ import { customElement, property, query, state } from 'lit/decorators.js'; import { profilesStoreContext } from '../context.js'; import { ProfilesStore } from '../profiles-store.js'; import { Profile } from '../types.js'; -import './agent-avatar.js'; import './profile-list-item-skeleton.js'; -import './search-agent-dropdown.js'; +import './search-profile-dropdown.js'; /** - * @element search-agent - * @fires agent-selected - Fired when the user selects some agent. Detail will have this shape: { agentPubKey: HoloHash } + * @element search-profile + * @fires profile-selected - Fired when the user selects some agent. Detail will have this shape: { agentPubKey: HoloHash } */ @localized() -@customElement('search-agent') -export class SearchAgent +@customElement('search-profile') +export class SearchProfile extends SignalWatcher(LitElement) implements FormField { @@ -48,7 +47,7 @@ export class SearchAgent * The default value of the field if this element is used inside a form */ @property(hashProperty('default-value')) - defaultValue: AgentPubKey | undefined; + defaultValue: ActionHash | undefined; /** * Whether this field is required if this element is used inside a form @@ -66,7 +65,7 @@ export class SearchAgent * @internal */ @state() - value!: AgentPubKey | undefined; + value!: ActionHash | undefined; /** Public attributes */ @@ -85,10 +84,10 @@ export class SearchAgent store!: ProfilesStore; /** - * Agents that won't be listed in the search + * Profiles that won't be listed in the search */ @property() - excludedAgents: AgentPubKey[] = []; + excludedProfiles: ActionHash[] = []; /** * Label for the agent searching field. @@ -116,8 +115,8 @@ export class SearchAgent async reset() { this.value = this.defaultValue; if (this.defaultValue) { - const profile = await this.store.client.getAgentProfile( - this.defaultValue, + const profile = await toPromise( + this.store.profiles.get(this.defaultValue).latestVersion, ); this._textField.value = profile?.entry.nickname || ''; } else { @@ -134,8 +133,8 @@ export class SearchAgent @state() searchFilter = ''; - onUsernameSelected(agentPubKey: AgentPubKey, profile: EntryRecord) { - this.value = agentPubKey; + onProfileSelected(profileHash: ActionHash, profile: EntryRecord) { + this.value = profileHash; // If the consumer says so, clear the field if (this.clearOnSelect) { @@ -150,7 +149,7 @@ export class SearchAgent * @internal */ get _label() { - let l = this.fieldLabel ? this.fieldLabel : msg('Search Agent'); + let l = this.fieldLabel ? this.fieldLabel : msg('Search Profile'); if (this.required !== false) l = `${l} *`; @@ -160,14 +159,14 @@ export class SearchAgent render() { return html`
- = 3} style="flex: 1" - .excludedAgents=${this.excludedAgents} + .excludedProfiles=${this.excludedProfiles} .searchFilter=${this.searchFilter} - @agent-selected=${(e: CustomEvent) => - this.onUsernameSelected(e.detail.agentPubKey, e.detail.profile)} + @profile-selected=${(e: CustomEvent) => + this.onProfileSelected(e.detail.profileHash, e.detail.profile)} > - +
`; } diff --git a/ui/src/elements/search-agents.ts b/ui/src/elements/search-profiles.ts similarity index 81% rename from ui/src/elements/search-agents.ts rename to ui/src/elements/search-profiles.ts index a9a823989..8d24868fd 100644 --- a/ui/src/elements/search-agents.ts +++ b/ui/src/elements/search-profiles.ts @@ -6,7 +6,7 @@ import { wrapPathInSvg, } from '@holochain-open-dev/elements'; import { SignalWatcher } from '@holochain-open-dev/signals'; -import { AgentPubKey } from '@holochain/client'; +import { ActionHash, AgentPubKey } from '@holochain/client'; import { consume } from '@lit/context'; import { localized, msg } from '@lit/localize'; import { mdiDelete } from '@mdi/js'; @@ -17,14 +17,14 @@ import { customElement, property, state } from 'lit/decorators.js'; import { profilesStoreContext } from '../context.js'; import { ProfilesStore } from '../profiles-store.js'; import './profile-list-item.js'; -import './search-agent.js'; +import './search-profile.js'; /** - * @element search-agents + * @element search-profiles */ @localized() -@customElement('search-agents') -export class SearchAgents +@customElement('search-profiles') +export class SearchProfiles extends SignalWatcher(LitElement) implements FormField { @@ -41,7 +41,7 @@ export class SearchAgents * The default value of the field if this element is used inside a form */ @property(hashProperty('default-value')) - defaultValue: Array = []; + defaultValue: Array = []; /** * Whether this field is required if this element is used inside a form @@ -85,7 +85,7 @@ export class SearchAgents * Agents that won't be listed in the search */ @property() - excludedAgents: AgentPubKey[] = []; + excludedProfiles: ActionHash[] = []; reportValidity() { return true; @@ -99,47 +99,47 @@ export class SearchAgents * @internal */ @state() - value: AgentPubKey[] = []; + value: ActionHash[] = []; render() { return html`
- { - this.value = [...this.value, e.detail.agentPubKey]; + @profile-selected=${(e: any) => { + this.value = [...this.value, e.detail.profileHash]; this.dispatchEvent( - new CustomEvent('agents-changed', { + new CustomEvent('profiles-changed', { composed: true, bubbles: true, detail: { - agents: this.value, + profilesHashes: this.value, }, }), ); }} - .excludedAgents=${this.excludedAgents} - > + .excludedProfiles=${this.excludedProfiles} + > ${this.value.length === 0 ? html`${this.emptyListPlaceholder}` : this.value.map( - (agent, i) => + (profileHash, i) => html`
{ this.value = this.value.filter((v, i2) => i2 !== i); this.dispatchEvent( - new CustomEvent('agents-changed', { + new CustomEvent('profiles-changed', { composed: true, bubbles: true, detail: { - agents: this.value, + profilesHashes: this.value, }, }), ); diff --git a/ui/src/elements/textarea-with-mentions.ts b/ui/src/elements/textarea-with-mentions.ts index 3f3cee54c..198035311 100644 --- a/ui/src/elements/textarea-with-mentions.ts +++ b/ui/src/elements/textarea-with-mentions.ts @@ -16,18 +16,18 @@ import { Plugin, PluginKey } from 'prosemirror-state'; import { profilesStoreContext } from '../context.js'; import { ProfilesStore } from '../profiles-store.js'; import './agent-mention.js'; -import { SearchAgentDropdown } from './search-agent-dropdown.js'; +import { SearchProfileDropdown } from './search-profile-dropdown.js'; -export const agentMentionSpec: NodeSpec = { - attrs: { agentPubKey: {} }, +export const profileMentionSpec: NodeSpec = { + attrs: { profileHash: {} }, inline: true, group: 'inline', draggable: true, toDOM: node => { console.log(node); return [ - 'agent-mention', - { 'agent-pub-key': encodeHashToBase64(node.attrs.agentPubKey) }, + 'profile-mention', + { 'profile-hash': encodeHashToBase64(node.attrs.profileHash) }, ]; }, parseDOM: [{ tag: 'agent-mention' }], @@ -35,7 +35,7 @@ export const agentMentionSpec: NodeSpec = { export type SearchAgentPluginState = | { - dropdownEl: SearchAgentDropdown; + dropdownEl: SearchProfileDropdown; mentionCharIndex: number; lastCharIndex: number; } @@ -44,19 +44,19 @@ const schema = new Schema({ nodes: { doc: { content: 'paragraph+' }, paragraph: { - content: '(text|agentMention)*', + content: '(text|profileMention)*', toDOM() { return ['p', 0]; }, }, text: {}, - agentMention: agentMentionSpec, + profileMention: profileMentionSpec, }, }); -const agentType = schema.nodes.agentMention; +const profileType = schema.nodes.profileMention; -export const pluginKey = new PluginKey('search-agent'); -export const searchAgentPlugin = new Plugin({ +export const pluginKey = new PluginKey('search-profile'); +export const searchProfilePlugin = new Plugin({ key: pluginKey, state: { init() { @@ -94,8 +94,8 @@ export const searchAgentPlugin = new Plugin({ } else if (text === '@') { const { top, left } = view.coordsAtPos(to); const dropdownEl = document.createElement( - 'search-agent-dropdown', - ) as SearchAgentDropdown; + 'search-profile-dropdown', + ) as SearchProfileDropdown; dropdownEl.innerHTML = `
`; dropdownEl.open = true; @@ -109,8 +109,8 @@ export const searchAgentPlugin = new Plugin({ }), ); - dropdownEl.addEventListener('agent-selected', (e: any) => { - const agentPubKey = e.detail.agentPubKey; + dropdownEl.addEventListener('profile-selected', (e: any) => { + const profileHash = e.detail.profileHash; const state = this.getState(view.state); if (!state || state === 'hidden') return; @@ -120,8 +120,8 @@ export const searchAgentPlugin = new Plugin({ tr.replaceRangeWith( state.mentionCharIndex, state.lastCharIndex + 1, - agentType.create({ - agentPubKey, + profileType.create({ + profileHash, }), ); @@ -293,7 +293,7 @@ export class TextareaWithMentions extends SlTextareaProsemirror { editorStateConfig() { return { schema, - plugins: [keymap(baseKeymap), searchAgentPlugin], + plugins: [keymap(baseKeymap), searchProfilePlugin], }; } } diff --git a/ui/src/elements/update-profile.ts b/ui/src/elements/update-profile.ts index f3969ba77..28ac9a8e8 100644 --- a/ui/src/elements/update-profile.ts +++ b/ui/src/elements/update-profile.ts @@ -1,6 +1,8 @@ import { sharedStyles } from '@holochain-open-dev/elements'; import '@holochain-open-dev/elements/dist/elements/display-error.js'; -import { SignalWatcher } from '@holochain-open-dev/signals'; +import { AsyncResult, SignalWatcher } from '@holochain-open-dev/signals'; +import { EntryRecord } from '@holochain-open-dev/utils'; +import { ActionHash } from '@holochain/client'; import { consume } from '@lit/context'; import { localized, msg } from '@lit/localize'; import '@shoelace-style/shoelace/dist/components/spinner/spinner.js'; @@ -26,8 +28,8 @@ export class UpdateProfile extends SignalWatcher(LitElement) { @property() store!: ProfilesStore; - async updateProfile(profile: Profile) { - await this.store.client.updateProfile(profile); + async updateProfile(previousProfileHash: ActionHash, profile: Profile) { + await this.store.client.updateProfile(previousProfileHash, profile); this.dispatchEvent( new CustomEvent('profile-updated', { @@ -40,8 +42,20 @@ export class UpdateProfile extends SignalWatcher(LitElement) { ); } - render() { + myProfile(): AsyncResult | undefined> { const myProfile = this.store.myProfile.get(); + if (myProfile.status !== 'completed') return myProfile; + if (!myProfile.value) { + return { + status: 'completed', + value: undefined, + }; + } + return myProfile.value.latestVersion.get(); + } + + render() { + const myProfile = this.myProfile(); switch (myProfile.status) { case 'pending': @@ -58,7 +72,7 @@ export class UpdateProfile extends SignalWatcher(LitElement) { .profile=${myProfile.value} .saveProfileLabel=${msg('Update Profile')} @save-profile=${(e: CustomEvent) => - this.updateProfile(e.detail.profile)} + this.updateProfile(myProfile.value!.actionHash, e.detail.profile)} >`; case 'error': return html` { constructor( @@ -19,17 +20,44 @@ export class ProfilesClient extends ZomeClient { } /** - * Get the profile for the given agent, if they have created it + * Get the profiles links for the given agent * - * @param agentPubKey the agent to get the profile for - * @returns the profile of the agent, if they have created one + * @param agentPubKey the agent to get the profileHash for + * @returns the links pointing to the profile of the agent, can't be more than one */ - async getAgentProfile( - agentPubKey: AgentPubKey, + async getAgentProfile(agentPubKey: AgentPubKey): Promise> { + return this.callZome('get_agent_profile', agentPubKey); + } + + /** + * Get the latest version of profile, if they have created it + * + * @param profileHash the profileHash to get the latest version for + * @returns the latest version of the profile + */ + async getLatestProfile( + profileHash: ActionHash, ): Promise | undefined> { const record: Record | undefined = await this.callZome( - 'get_agent_profile', - agentPubKey, + 'get_latest_profile', + profileHash, + ); + + return record ? new EntryRecord(record) : undefined; + } + + /** + * Get the original profile for the given agent, if they have created it + * + * @param profileHash the profileHash to get the original version for + * @returns the original version of the profile + */ + async getOriginalProfile( + profileHash: ActionHash, + ): Promise | undefined> { + const record: Record | undefined = await this.callZome( + 'get_original_profile', + profileHash, ); return record ? new EntryRecord(record) : undefined; @@ -41,17 +69,17 @@ export class ProfilesClient extends ZomeClient { * @param nicknameFilter must be of at least 3 characters * @returns the agents with the nickname starting with nicknameFilter */ - async searchAgents(nicknameFilter: string): Promise { - return this.callZome('search_agents', nicknameFilter); + async searchProfiles(nicknameFilter: string): Promise { + return this.callZome('search_profiles', nicknameFilter); } /** - * Get all the agents in the DHT that have created a profile + * Get links to all profiles in the DHT * - * @returns the agent public keys of all agents that have created a profile + * @returns the links with targets to all the profiles */ - async getAgentsWithProfile(): Promise { - return this.callZome('get_agents_with_profile', null); + async getAllProfiles(): Promise { + return this.callZome('get_all_profiles', null); } /** @@ -69,8 +97,51 @@ export class ProfilesClient extends ZomeClient { * * @param profile the profile to create */ - async updateProfile(profile: Profile): Promise> { - const record: Record = await this.callZome('update_profile', profile); + async updateProfile( + previousProfileHash: ActionHash, + updatedProfile: Profile, + ): Promise> { + const record: Record = await this.callZome('update_profile', { + previous_profile_hash: previousProfileHash, + updated_profile: updatedProfile, + }); + return new EntryRecord(record); + } + + /** Devices linking functions */ + + /** + * Links the given agent under the profile for the caller agent + * WARNING! Only call this function if you are completely confident that the linked + * agent belongs to the same person as this agent + * + * @returns the records for all the ProfileClaims in this source chain + */ + linkAgentWithMyProfile(agentPubKey: AgentPubKey) { + return this.callZome('link_agent_with_my_profile', agentPubKey); + } + + /** + * Queries the ProfileClaim entries stored in this agent's source chain + * + * @returns the records for all the ProfileClaims in this source chain + */ + async queryMyProfileClaims(): Promise[]> { + return this.callZome('query_my_profile_claims', null); + } + + /** + * Create ProfileClaim + * + * @param profileClaim the ProfileClaim to create + */ + async createProfileClaim( + profileClaim: ProfileClaim, + ): Promise> { + const record: Record = await this.callZome( + 'create_profile_claim', + profileClaim, + ); return new EntryRecord(record); } } diff --git a/ui/src/profiles-store.ts b/ui/src/profiles-store.ts index 963339956..344081770 100644 --- a/ui/src/profiles-store.ts +++ b/ui/src/profiles-store.ts @@ -1,109 +1,164 @@ import { - AsyncComputed, - AsyncState, - Signal, collectionSignal, - joinAsyncMap, + immutableEntrySignal, + latestVersionOfEntrySignal, + liveLinksSignal, mapCompleted, + pipe, + queryLiveEntriesSignal, } from '@holochain-open-dev/signals'; -import { - EntryRecord, - HashType, - LazyHoloHashMap, - mapValues, - retype, - slice, -} from '@holochain-open-dev/utils'; -import { AgentPubKey } from '@holochain/client'; -import { encode } from '@msgpack/msgpack'; +import { LazyHoloHashMap, slice } from '@holochain-open-dev/utils'; +import { ActionHash, AgentPubKey, encodeHashToBase64 } from '@holochain/client'; import { ProfilesConfig, defaultConfig } from './config.js'; import { ProfilesClient } from './profiles-client.js'; -import { Profile } from './types.js'; +import { effect } from './utils.js'; export class ProfilesStore { config: ProfilesConfig; + protected _creatingClaim = false; + constructor( public client: ProfilesClient, config: Partial = {}, ) { this.config = { ...defaultConfig, ...config }; + + effect(() => { + const claims = this.myProfileClaims.get(); + + const agentToProfileLinks = this.agentToProfileLinks + .get(this.client.client.myPubKey) + .get(); + if (claims.status !== 'completed') return; + if (agentToProfileLinks.status !== 'completed') return; + + const myLinks = agentToProfileLinks.value.filter( + l => + encodeHashToBase64(l.author) === + encodeHashToBase64(this.client.client.myPubKey), + ); + + if ( + claims.value.length === 0 && + agentToProfileLinks.value.length > 0 && + myLinks.length === 0 + ) { + if (this._creatingClaim) return; + this._creatingClaim = true; + const link = agentToProfileLinks.value[0]; + this.client + .createProfileClaim({ + profile_hash: link.target, + agent_to_profile_create_link_hash: link.create_link_hash, + }) + .then(() => (this._creatingClaim = false)) + .catch(() => (this._creatingClaim = false)); + } + }); } /** - * Fetches all the agents that have created a profile in the DHT + * Fetches the profiles for all agents in the DHT */ - agentsWithProfile = mapCompleted( + allProfiles = mapCompleted( collectionSignal( this.client, - () => this.client.getAgentsWithProfile(), - 'PathToAgent', + () => this.client.getAllProfiles(), + 'PathToProfile', ), - links => links.map(l => retype(l.target, HashType.AGENT)), + links => { + const profileTargets = links.map(l => l.target); + return slice(this.profiles, profileTargets); + }, ); - /** - * Fetches the profiles for all agents in the DHT - * - * This will get slower as the number of agents in the DHT increases - */ - allProfiles = new AsyncComputed(() => { - const agentsWithProfile = this.agentsWithProfile.get(); - if (agentsWithProfile.status !== 'completed') return agentsWithProfile; + private agentToProfileLinks = new LazyHoloHashMap((agent: AgentPubKey) => + liveLinksSignal( + this.client, + agent, + () => this.client.getAgentProfile(agent), + 'AgentToProfile', + 100, + ), + ); - const allProfiles = slice(this.profiles, agentsWithProfile.value); - return joinAsyncMap(mapValues(allProfiles, p => p.get())); - }); + agentProfile = new LazyHoloHashMap((agent: AgentPubKey) => + pipe(this.agentToProfileLinks.get(agent), links => { + if (links.length > 1) throw new Error('Agent has more than one profile'); + if (links.length === 0) return undefined; + + const profileHash = links[0].target; + return this.profiles.get(profileHash); + }), + ); /** * Fetches the profile for the given agent */ - profiles = new LazyHoloHashMap((agent: AgentPubKey) => { - let unsubscribe: (() => void) | undefined; - const signal = new AsyncState | undefined>( - { status: 'pending' }, - { - [Signal.subtle.watched]: async () => { - const value = await this.client.getAgentProfile(agent); - signal.set({ - status: 'completed', - value, - }); - unsubscribe = this.client.onSignal(profilesSignal => { - if (this.client.client.myPubKey.toString() !== agent.toString()) - return; - if ( - !( - profilesSignal.type === 'EntryCreated' || - profilesSignal.type === 'EntryUpdated' - ) - ) - return; - const record = new EntryRecord({ - entry: { - Present: { - entry_type: 'App', - entry: encode(profilesSignal.app_entry), - }, - }, - signed_action: profilesSignal.action, - }); - signal.set({ - status: 'completed', - value: record, - }); - }); - }, - [Signal.subtle.unwatched]: () => { - signal.set({ status: 'pending' }); - unsubscribe?.(); - }, - }, - ); - return signal; - }); + profiles = new LazyHoloHashMap( + (profileHash: ActionHash) => ({ + profileHash, + latestVersion: latestVersionOfEntrySignal(this.client, () => + this.client.getLatestProfile(profileHash), + ), + original: immutableEntrySignal(() => + this.client.getOriginalProfile(profileHash), + ), + }), + // { + // let unsubscribe: (() => void) | undefined; + // const signal = new AsyncState | undefined>( + // { status: 'pending' }, + // { + // [Signal.subtle.watched]: async () => { + // const value = await this.client.getAgentProfile(agent); + // signal.set({ + // status: 'completed', + // value, + // }); + // unsubscribe = this.client.onSignal(profilesSignal => { + // if (this.client.client.myPubKey.toString() !== agent.toString()) + // return; + // if ( + // !( + // profilesSignal.type === 'EntryCreated' || + // profilesSignal.type === 'EntryUpdated' + // ) + // ) + // return; + // const record = new EntryRecord({ + // entry: { + // Present: { + // entry_type: 'App', + // entry: encode(profilesSignal.app_entry), + // }, + // }, + // signed_action: profilesSignal.action, + // }); + // signal.set({ + // status: 'completed', + // value: record, + // }); + // }); + // }, + // [Signal.subtle.unwatched]: () => { + // signal.set({ status: 'pending' }); + // unsubscribe?.(); + // }, + // }, + // ); + // return signal; + // } + ); // Fetches the profile for the active agent - myProfile = this.profiles.get(this.client.client.myPubKey); + myProfile = this.agentProfile.get(this.client.client.myPubKey); + + myProfileClaims = queryLiveEntriesSignal( + this.client, + () => this.client.queryMyProfileClaims(), + 'ProfileClaim', + ); } diff --git a/ui/src/types.ts b/ui/src/types.ts index 3078b1d56..872f78037 100644 --- a/ui/src/types.ts +++ b/ui/src/types.ts @@ -1,10 +1,18 @@ -import { ActionCommittedSignal } from "@holochain-open-dev/utils"; +import { ActionCommittedSignal } from '@holochain-open-dev/utils'; +import { ActionHash } from '@holochain/client'; export type ProfilesSignal = ActionCommittedSignal; -export type EntryTypes = { type: "Profile" } & Profile; +export type EntryTypes = + | ({ type: 'Profile' } & Profile) + | ({ type: 'ProfileClaim' } & ProfileClaim); export interface Profile { - nickname: string; - fields: Record; + nickname: string; + fields: Record; +} + +export interface ProfileClaim { + profile_hash: ActionHash; + agent_to_profile_create_link_hash: ActionHash; } diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 841bbb058..54f2c73fd 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -1,7 +1,10 @@ -import { HoloHash } from "@holochain/client"; +import { Signal } from '@holochain-open-dev/signals'; +import { HoloHash } from '@holochain/client'; - -export function areHashesArraysEqual(hashes1: HoloHash[], hashes2: HoloHash[]): boolean { +export function areHashesArraysEqual( + hashes1: HoloHash[], + hashes2: HoloHash[], +): boolean { if (hashes1.length !== hashes2.length) return false; for (let i = 0; i < hashes1.length; i++) { @@ -11,3 +14,39 @@ export function areHashesArraysEqual(hashes1: HoloHash[], hashes2: HoloHash[]): } return true; } + +// NOTE: This scheduling logic is too basic to be useful. Do not copy/paste. +// This function would usually live in a library/framework, not application code +let pending = false; + +const w = new Signal.subtle.Watcher(() => { + if (!pending) { + pending = true; + queueMicrotask(() => { + pending = false; + for (const s of w.getPending()) s.get(); + w.watch(); + }); + } +}); + +// TODO: why do we need to use this complicated effect method? +// An effect effect Signal which evaluates to cb, which schedules a read of +// itself on the microtask queue whenever one of its dependencies might change +export function effect(cb: any) { + let destructor: any; + const c = new Signal.Computed(() => { + if (typeof destructor === 'function') { + destructor(); + } + destructor = cb(); + }); + w.watch(c); + c.get(); + return () => { + if (typeof destructor === 'function') { + destructor(); + } + w.unwatch(c); + }; +}