diff --git a/package-lock.json b/package-lock.json index c1ae3e8..4baa6e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -466,9 +466,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -3316,6 +3316,11 @@ "@types/tern": "*" } }, + "node_modules/@types/console-log-tree": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/console-log-tree/-/console-log-tree-1.2.2.tgz", + "integrity": "sha512-xnScJjLo9FMSyXpgy4xKkkGMc11oO2gffKeTcZa5W9N/8Lx1rzkAOY6kLOGkAWC8q65xJY9bwYQ+JxN0i3E/YA==" + }, "node_modules/@types/estree": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", @@ -3696,6 +3701,127 @@ "pretty-format": "^27.5.1" } }, + "node_modules/@volar/language-core": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.5.tgz", + "integrity": "sha512-xD71j4Ee0Ycq8WsiAE6H/aCThGdTobiZZeD+jFD+bvmbopa1Az296pqJysr3Ck8c7n5+GGF+xlKCS3WxRFYgSQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@volar/source-map": "1.10.5" + } + }, + "node_modules/@volar/source-map": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.5.tgz", + "integrity": "sha512-s4kgo66SA1kMzYvF9HFE6Vc1rxtXLUmcLrT2WKnchPDvLne+97Kw+xoR2NxJFmsvHoL18vmu/YGXYcN+Q5re1g==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "muggle-string": "^0.3.1" + } + }, + "node_modules/@volar/typescript": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.5.tgz", + "integrity": "sha512-kfDehpeLJku9i1BgsFOYIczPmFFH4herl+GZrLGdvX5urTqeCKsKYlF36iNmFaADzjMb9WlENcUZzPjK8MxNrQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@volar/language-core": "1.10.5" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.7.tgz", + "integrity": "sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@babel/parser": "^7.23.0", + "@vue/shared": "3.3.7", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.7.tgz", + "integrity": "sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@vue/compiler-core": "3.3.7", + "@vue/shared": "3.3.7" + } + }, + "node_modules/@vue/language-core": { + "version": "1.8.21", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.21.tgz", + "integrity": "sha512-dKQJc1xfWIZfv6BeXyxz3SSNrC7npJpDIN/VOb1rodAm4o247TElrXOHYAJdV9x1KilaEUo3YbnQE+WA3vQwMw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@volar/language-core": "~1.10.5", + "@volar/source-map": "~1.10.5", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "vue-template-compiler": "^2.7.14" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vue/language-core/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vue/shared": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.7.tgz", + "integrity": "sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/@web/config-loader": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@web/config-loader/-/config-loader-0.1.3.tgz", @@ -4492,6 +4618,14 @@ "resolved": "https://registry.npmjs.org/composed-offset-position/-/composed-offset-position-0.0.4.tgz", "integrity": "sha512-vMlvu1RuNegVE0YsCDSV/X4X10j56mq7PCIyOKK74FxkXzGLwhOUmdkJLSdOBOMwWycobGUMgft2lp+YgTe8hw==" }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4683,6 +4817,14 @@ "url": "https://opencollective.com/date-fns" } }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -5697,6 +5839,14 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6235,6 +6385,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "he": "bin/he" + } + }, "node_modules/htmlparser2": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", @@ -6976,6 +7137,14 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -7407,9 +7576,9 @@ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" }, "node_modules/playground-exercise": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/playground-exercise/-/playground-exercise-0.1.2.tgz", - "integrity": "sha512-yIQoXTHxvmdb1ABP7jFuarB6SwgZycQ266i+HDHOzgaWco+Ke40xekikvZE4t2akVzenWh5nALsUF4wYGp1wwg==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/playground-exercise/-/playground-exercise-0.1.3.tgz", + "integrity": "sha512-HmjDLYGDZhta9RkJ7zGOS4y8F8rv7xar2jBgi27a902KpM5ZCU1gDC+b27VbXQUV9DjR3xNkKtGw1CrJTJ5KGg==", "dependencies": { "@mdi/js": "^7.3.67", "@shoelace-style/shoelace": "^2.11.0", @@ -9167,6 +9336,76 @@ "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==", "dev": true }, + "node_modules/vue-template-compiler": { + "version": "2.7.15", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.15.tgz", + "integrity": "sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "1.8.21", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.21.tgz", + "integrity": "sha512-gc9e+opdeF0zKixaadXT5v2s+x+77oqpuza/vwqDhdDyEeLZUOmZaVeb9noZpkdhFaLq7t7ils/7lFU8E/Hgew==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@volar/typescript": "~1.10.5", + "@vue/language-core": "1.8.21", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/vue-tsc/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-tsc/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-tsc/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", @@ -9413,10 +9652,11 @@ }, "packages/stores": { "name": "@holochain-open-dev/stores", - "version": "0.7.4", + "version": "0.7.7", "dependencies": { - "@holochain-open-dev/utils": "^0.15.0", + "@holochain-open-dev/utils": "^0.16.1", "@holochain/client": "^0.16.0", + "@types/console-log-tree": "^1.2.2", "console-log-tree": "^1.2.1", "lit-svelte-stores": "^0.2.1", "svelte": "^3.53.1" @@ -9431,22 +9671,9 @@ "vitest": "^0.28.5" } }, - "packages/stores/node_modules/@holochain-open-dev/utils": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@holochain-open-dev/utils/-/utils-0.15.2.tgz", - "integrity": "sha512-QW5l0R6tPQFxM4Jj+tJg5mbjJH+ejLbaCgAan3jLXGqEclwlDQAM2Qzq+yAmvju/F4ELduybjrZUqsV+jhouag==", - "dependencies": { - "@holochain/client": "^0.16.2", - "@msgpack/msgpack": "^2.7.2", - "blakejs": "^1.2.1", - "emittery": "^1.0.1", - "lodash-es": "^4.17.21", - "sort-keys": "^5.0.0" - } - }, "packages/utils": { "name": "@holochain-open-dev/utils", - "version": "0.16.0", + "version": "0.16.1", "dependencies": { "@holochain/client": "^0.16.2", "@msgpack/msgpack": "^2.7.2", @@ -9470,7 +9697,7 @@ "license": "MIT", "dependencies": { "@mythosthesia/reveal-course-preset": "^0.1.5", - "playground-exercise": "^0.1.2", + "playground-exercise": "^0.1.3", "reveal.js": "=4.3.1", "typed-js": "^0.2.3" }, @@ -9809,9 +10036,9 @@ } }, "@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -10928,8 +11155,9 @@ "version": "file:packages/stores", "requires": { "@esm-bundle/chai": "^4.3.4-fix.0", - "@holochain-open-dev/utils": "^0.15.0", + "@holochain-open-dev/utils": "^0.16.1", "@holochain/client": "^0.16.0", + "@types/console-log-tree": "*", "@types/lodash-es": "^4.17.6", "concurrently": "^7.0.0", "console-log-tree": "^1.2.1", @@ -10939,21 +11167,6 @@ "typescript": "^4.4.3", "vite": "^4.1.1", "vitest": "^0.28.5" - }, - "dependencies": { - "@holochain-open-dev/utils": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@holochain-open-dev/utils/-/utils-0.15.2.tgz", - "integrity": "sha512-QW5l0R6tPQFxM4Jj+tJg5mbjJH+ejLbaCgAan3jLXGqEclwlDQAM2Qzq+yAmvju/F4ELduybjrZUqsV+jhouag==", - "requires": { - "@holochain/client": "^0.16.2", - "@msgpack/msgpack": "^2.7.2", - "blakejs": "^1.2.1", - "emittery": "^1.0.1", - "lodash-es": "^4.17.21", - "sort-keys": "^5.0.0" - } - } } }, "@holochain-open-dev/utils": { @@ -12100,6 +12313,11 @@ "@types/tern": "*" } }, + "@types/console-log-tree": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/console-log-tree/-/console-log-tree-1.2.2.tgz", + "integrity": "sha512-xnScJjLo9FMSyXpgy4xKkkGMc11oO2gffKeTcZa5W9N/8Lx1rzkAOY6kLOGkAWC8q65xJY9bwYQ+JxN0i3E/YA==" + }, "@types/estree": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", @@ -12388,6 +12606,115 @@ "pretty-format": "^27.5.1" } }, + "@volar/language-core": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.5.tgz", + "integrity": "sha512-xD71j4Ee0Ycq8WsiAE6H/aCThGdTobiZZeD+jFD+bvmbopa1Az296pqJysr3Ck8c7n5+GGF+xlKCS3WxRFYgSQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@volar/source-map": "1.10.5" + } + }, + "@volar/source-map": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.5.tgz", + "integrity": "sha512-s4kgo66SA1kMzYvF9HFE6Vc1rxtXLUmcLrT2WKnchPDvLne+97Kw+xoR2NxJFmsvHoL18vmu/YGXYcN+Q5re1g==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "muggle-string": "^0.3.1" + } + }, + "@volar/typescript": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.5.tgz", + "integrity": "sha512-kfDehpeLJku9i1BgsFOYIczPmFFH4herl+GZrLGdvX5urTqeCKsKYlF36iNmFaADzjMb9WlENcUZzPjK8MxNrQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@volar/language-core": "1.10.5" + } + }, + "@vue/compiler-core": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.7.tgz", + "integrity": "sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@babel/parser": "^7.23.0", + "@vue/shared": "3.3.7", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" + } + }, + "@vue/compiler-dom": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.7.tgz", + "integrity": "sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@vue/compiler-core": "3.3.7", + "@vue/shared": "3.3.7" + } + }, + "@vue/language-core": { + "version": "1.8.21", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.21.tgz", + "integrity": "sha512-dKQJc1xfWIZfv6BeXyxz3SSNrC7npJpDIN/VOb1rodAm4o247TElrXOHYAJdV9x1KilaEUo3YbnQE+WA3vQwMw==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@volar/language-core": "~1.10.5", + "@volar/source-map": "~1.10.5", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "vue-template-compiler": "^2.7.14" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@vue/shared": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.7.tgz", + "integrity": "sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg==", + "dev": true, + "optional": true, + "peer": true + }, "@web/config-loader": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@web/config-loader/-/config-loader-0.1.3.tgz", @@ -12950,6 +13277,14 @@ "resolved": "https://registry.npmjs.org/composed-offset-position/-/composed-offset-position-0.0.4.tgz", "integrity": "sha512-vMlvu1RuNegVE0YsCDSV/X4X10j56mq7PCIyOKK74FxkXzGLwhOUmdkJLSdOBOMwWycobGUMgft2lp+YgTe8hw==" }, + "computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true, + "optional": true, + "peer": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -13094,6 +13429,14 @@ "@babel/runtime": "^7.21.0" } }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "optional": true, + "peer": true + }, "debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -13865,6 +14208,14 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "optional": true, + "peer": true + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -14259,6 +14610,14 @@ "has-symbols": "^1.0.2" } }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "optional": true, + "peer": true + }, "htmlparser2": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", @@ -14828,6 +15187,14 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true, + "optional": true, + "peer": true + }, "nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -15159,9 +15526,9 @@ } }, "playground-exercise": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/playground-exercise/-/playground-exercise-0.1.2.tgz", - "integrity": "sha512-yIQoXTHxvmdb1ABP7jFuarB6SwgZycQ266i+HDHOzgaWco+Ke40xekikvZE4t2akVzenWh5nALsUF4wYGp1wwg==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/playground-exercise/-/playground-exercise-0.1.3.tgz", + "integrity": "sha512-HmjDLYGDZhta9RkJ7zGOS4y8F8rv7xar2jBgi27a902KpM5ZCU1gDC+b27VbXQUV9DjR3xNkKtGw1CrJTJ5KGg==", "requires": { "@mdi/js": "^7.3.67", "@shoelace-style/shoelace": "^2.11.0", @@ -15714,7 +16081,7 @@ "@babel/preset-env": "^7.16.4", "@mythosthesia/reveal-course-preset": "^0.1.5", "deepmerge": "^4.2.2", - "playground-exercise": "^0.1.2", + "playground-exercise": "^0.1.3", "reveal.js": "=4.3.1", "rimraf": "^3.0.2", "typed-js": "^0.2.3", @@ -16394,6 +16761,63 @@ "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==", "dev": true }, + "vue-template-compiler": { + "version": "2.7.15", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.15.tgz", + "integrity": "sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "vue-tsc": { + "version": "1.8.21", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.21.tgz", + "integrity": "sha512-gc9e+opdeF0zKixaadXT5v2s+x+77oqpuza/vwqDhdDyEeLZUOmZaVeb9noZpkdhFaLq7t7ils/7lFU8E/Hgew==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@volar/typescript": "~1.10.5", + "@vue/language-core": "1.8.21", + "semver": "^7.5.4" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "optional": true, + "peer": true + } + } + }, "w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", diff --git a/packages/stores/package.json b/packages/stores/package.json index 2eb76f9..47d82b9 100644 --- a/packages/stores/package.json +++ b/packages/stores/package.json @@ -1,6 +1,6 @@ { "name": "@holochain-open-dev/stores", - "version": "0.7.5", + "version": "0.7.7", "description": "Re-export of svelte/store, with additional utilities to build reusable holochain-open-dev modules", "author": "guillem.cordoba@gmail.com", "main": "dist/index.js", @@ -8,7 +8,8 @@ "types": "dist/index.d.ts", "files": ["dist"], "exports": { - ".": "./dist/index.js" + ".": "./dist/index.js", + "./dist/*": "./dist/*" }, "scripts": { "start": "vite --open", @@ -17,14 +18,16 @@ "test": "vitest run" }, "dependencies": { - "@holochain-open-dev/utils": "^0.15.0", + "@holochain-open-dev/utils": "^0.16.1", "@holochain/client": "^0.16.0", + "console-log-tree": "^1.2.1", "lit-svelte-stores": "^0.2.1", "svelte": "^3.53.1" }, "devDependencies": { "@esm-bundle/chai": "^4.3.4-fix.0", "@types/lodash-es": "^4.17.6", + "@types/console-log-tree": "^1.2.2", "concurrently": "^7.0.0", "rimraf": "^3.0.2", "typescript": "^4.4.3", diff --git a/packages/stores/src/async-readable.ts b/packages/stores/src/async-readable.ts index 81f4fdc..627c9c3 100644 --- a/packages/stores/src/async-readable.ts +++ b/packages/stores/src/async-readable.ts @@ -1,4 +1,4 @@ -import { isEqual } from "lodash-es"; +import isEqual from "lodash-es/isEqual.js"; import { readable, Readable, Subscriber, Unsubscriber } from "svelte/store"; export type AsyncStatus = diff --git a/packages/utils/package.json b/packages/utils/package.json index 8385a9a..0d24944 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@holochain-open-dev/utils", - "version": "0.16.0", + "version": "0.16.1", "description": "Common utilities to build Holochain web applications", "author": "guillem.cordoba@gmail.com", "main": "dist/index.js", diff --git a/packages/utils/src/hash.ts b/packages/utils/src/hash.ts index 9f1d8f5..906dec1 100644 --- a/packages/utils/src/hash.ts +++ b/packages/utils/src/hash.ts @@ -4,7 +4,7 @@ import blake from "blakejs"; import { encode } from "@msgpack/msgpack"; import { Base64 } from "js-base64"; import sortKeys from "sort-keys"; -import { isPlainObject } from "lodash-es"; +import isPlainObject from "lodash-es/isPlainObject.js"; export enum HashType { AGENT, diff --git a/sites/stores/index.html b/sites/stores/index.html index 74a8d30..fa8159e 100644 --- a/sites/stores/index.html +++ b/sites/stores/index.html @@ -17,6 +17,19 @@ @holochain-open-dev/stores +
@@ -24,6 +37,36 @@

@holochain-open-dev/stores

Reactive stores to build hApps

+
  • + Click on the blue arrow on the bottom right corner to advance! +
  • + + + - State management for web-apps + - Re-export of svelte stores, but with additional tooling on top of it + - Tuned specifically to the holochain architecture + + ### Features + + - Push-based + - Extensible + - Composable + - Enables developers to create clear interfaces between components + + ### Cons + + - Difficult to dive into it if you haven't done reactive programming before (eg. haskell, RxJS) + - Thus this tutorial! + - This is an experiment, and feedback is very well appreciated in [the issues page](https://github.com/holochain-open-dev/common)! + + ### Tutorial + + - In this tutorial, you will find an incremental approach to learning concepts + - Each slide will contain a minimal explanation of the concept, a code example, and a code exercise + - The concepts build heavily on each other, so I recommend actually doing the code example + - Have fun! + +
    @@ -44,13 +87,13 @@

    Reactive stores to build hApps

    // After some other code has executed... unsubscribe(); // Unsubscribes from the store, from this point on new - // values from the store won't get logged + // values from the store will not be logged } - #### Exercise + #### Complete This Exercise: @@ -69,7 +112,7 @@

    Reactive stores to build hApps

    } + + +
    +
    + +
    + + + ## lazy Load + + - Builds a simple `AsyncReadable` from the execution of a promise + - The promise will only execute when the store is subscribed to for the first time + - After all subscribers have unsubscribed, it will clear its value + + +
    
    +const lazyStore = lazyLoad(() => fetch('/some/big/request')); // Build the store
    +                                                              // **No request is done yet**
    +const unsubscribe1 = lazyStore.subscribe(value => console.log(value)); // Now the request is made
    +
    +// After a while...
    +
    +const unsubscribe2 = lazyStore.subscribe(value => console.log(value)); // No new request is made, the
    +                                                                       // status is automatically "complete"
    +
    + + + + #### Complete This Exercise: + + + + + + + + + + +
    + +
    + + + ## lazy Load And Poll + + - Builds an `AsyncReadable` that executes the given promise on a polling interval whenever it has subscribers + - After all subscribers have unsubscribed, it will clear its value + + +
    
    +const lazyStore = lazyLoadAndPoll(
    +  () => fetch('/some/big/request'), 
    +  4000 // Polling interval in ms 
    +); // Build the store, **no request is done yet**
    +const unsubscribe = lazyStore.subscribe(value => console.log(value)); // Now the request is made
    +                                                                      // And will continually be made every 4 seconds
    +// After a while...
    +
    +unsubscribe(); // Polling stops
    +
    + + + + #### Complete This Exercise: + + + + + + + + + + +
    + +
    + + + ## Lazy Holo Hash Map + + - Similar to standard javascript HashMap, but only exposes a `get(key: HoloHash)` method, and not any `set()` methods + - Receives a function in its constructor, of the form "(hash: HoloHash) => T" + - Whenever `get(key: HoloHash)` is called: + - If it's the first time this key is requested, it will execute the function defined in the constructor, store it in the map, and return that value + - Any later time, it will just return the value stored with that key + + +
    
    +const lazyMap = new LazyHoloHashMap((agent: AgentPubKey) => // Define the fn to execute for new gets 
    +  lazyLoadAndPoll(() => getAllPosts(agent), 4000) // Builds a new store that keeps polling whenever a new agent is requested
    +);
    +const myPostsStore1 = lazyMap.get(client.myPubKey); // Builds the store bound to "myPubKey"
    +const myPostsStore2 = lazyMap.get(client.myPubKey); // Does not build a new store, just returns the same one
    +const unsubscribe1 = myPostsStore.subscribe(value => console.log(value)); // Now the request is made
    +                                                                          // And will continually be made every 4 seconds
    +const unsubscribe2 = myPostsStore.subscribe(value => console.log(value)); // No other requests are made, the polling is already active
    +// After a while...
    +unsubscribe1(); // Polling does not stop
    +unsubscribe2(); // Last subscriber unsubscribes, polling stops
    +
    + + + + #### Complete This Exercise: + + + + + + + + + + +
    + +
    + + + ## Derived + + - Receives a store or an array of stores, and a mapping function to convert their values into some other derived value + + +
    
    +export function deriveAllPosts(alicePostsStore: Readable<Post[]>, bobPostsStore: Readable<Post[]>): Readable<Posts[]> {
    +  return derived([alicePostsStore, bobPostsStore], 
    +    ([alicePosts, bobPosts]) => [...alicePosts, ...bobPosts] // Will be called any time either `alicePostsStore` 
    +                                                             // or `bobPostsStore` are updated
    +  );
    +}
    +
    + + + + #### Complete This Exercise: + + + + + + + + + +
    + +
    + + + ## Async Derived + + - Similar to `derived`, but for `AsyncReadable` stores, and can only accept one store + - The derive function will only get executed when the status of the input store is complete + + +
    
    +export function deriveFilterEmptyPosts(postsStore: AsyncReadable<Post[]>): AsyncReadable<Posts[]> {
    +  return asyncDerived(postsStore, 
    +    (posts) => posts.filter(post => post.content.length > 0) // Will be called when `postsStore` has status "complete"
    +                                                             // and then every time it is updated
    +  );
    +}
    +
    + + + + #### Complete This Exercise: + + + + + + + + + + +
    + +
    + + + ## join Async + + - Takes an array of `AsyncReadable` stores, and joins them to return a single `AsyncReadable` of the array of the completed values of the stores + - If any store has status "pending", the joined store will have status "pending" + - If any store has status "error", the joined store will have status "error" and will contain the first error + + +
    
    +export function deriveAllPosts(alicePostsStore: AsyncReadable<Post[]>, bobPostsStore: AsyncReadable<Post[]>): AsyncReadable<Posts[]> {
    +  return asyncDerived(joinAsync([alicePostsStore, bobPostsStore]), // Creates an `AsyncReadable<[Array<Post>, Array<Post>]>`
    +    ([alicePosts, bobPosts]) => [...alicePosts, ...bobPosts] // Will be called any time either `alicePostsStore` 
    +                                                             // or `bobPostsStore` are updated
    +  );
    +}
    +
    + + + + #### Complete This Exercise: + + + + + + + + + + + +
    + +
    + + + ## slice and join + + - Takes a `HoloHashMap` of `AsyncReadable` stores, and an array of hashes, and: + - Does a `get(hash)` for each one of the given hashes + - Returns those stores joined in a map + - If any store has status "pending", the joined store will have status "pending" + - If any store has status "error", the joined store will have status "error" and will contain the first error + + +
    
    +// Imagine for some reason we need to display the latest content for all the posts in the app,
    +// and we already have a `LazyHoloHashMap` for the latest version of each of them
    +export function latestVersionOfAllPosts(
    +  allPosts: ActionHash[], 
    +  latestVersionOfPostsMap: LazyHoloHashMap<ActionHash, AsyncReadable<Post>>
    +): AsyncReadable<ReadonlyMap<ActionHash, Posts>> {
    +  return sliceAndJoin(latestVersionOfPostsMap, allPosts); // Will do a get for each post ActionHash
    +                                                          // If some of the posts were already loaded, 
    +                                                          // it will not need to make any new requests
    +}
    +
    + + + + #### Complete This Exercise: + + + + + + + + +
    + +
    + + + ## pipe + + - Takes an `AsyncReadable`, and applies any number of steps to derive the desired value + - Each of the steps can return a raw value, a promise, another `AsyncReadable` or a `Readable` of any other value + + +
    
    +// Imagine for some reason we need to display the latest content for all the posts in the app,
    +// we already have a `LazyHoloHashMap` for the latest version of each of them
    +// and an `AsyncReadable` for all the post hashes in the app
    +export function latestVersionOfAllPosts(
    +  allPostsStore: AsyncReadable<ActionHash[]>, 
    +  latestVersionOfPostsMap: LazyHoloHashMap<ActionHash, AsyncReadable<Post>>
    +): AsyncReadable<ReadonlyMap<ActionHash, Posts>> {
    +  return pipe(allPostsStore, // We pipe from the `allPostsStore`
    +    (postsHashes: ActionHash[]) => // The argument of each step is the result value of the previous one
    +                                   // In this case, it is the list of post hashes 
    +      sliceAndJoin(latestVersionOfPostsMap, postHashes) // And then, we just return the already familiar "sliceAndJoin" 
    +  ); 
    +}
    +
    + + + + #### Complete This Exercise: + + + + + + + + +
    + +
    + + + ## That's it! + + - That's it for the concepts + - The exercises are designed to be as minimal as possible to actual train the required skill + - You can imagine needing complex pipes to build your own stores in your app + - A big thank you to svelte for the inspiration and actual core of the stores implementation + + ### Real-world Examples + + - [ProfilesStore](https://github.com/holochain-open-dev/profiles/blob/main/ui/src/profiles-store.ts) + - [CancellationsStore](https://github.com/holochain-open-dev/cancellations/blob/main/ui/src/cancellations-store.ts) + - [WeStore](https://github.com/lightningrodlabs/we/blob/main/ui/app/src/we-store.ts) + - [GatherStore](https://github.com/darksoil-studio/gather/blob/main/ui/src/gather/gather/gather-store.ts) + + ### Future improvements on the library + + - Most of the usages of `lazyLoadAndPoll()` will be replaced by a fully pushed based approach based on signals + - This depends on holochain implementing the pub/sub system + +
    +
    +

    That's it!

    @@ -132,6 +969,8 @@

    Reactive stores to build hApps

    deck.initialize({ ...config, keyboard: false, + minScale: 1, + maxScale: 1, }); diff --git a/sites/stores/package.json b/sites/stores/package.json index 5f67b35..9f2793c 100644 --- a/sites/stores/package.json +++ b/sites/stores/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@mythosthesia/reveal-course-preset": "^0.1.5", - "playground-exercise": "^0.1.2", + "playground-exercise": "^0.1.3", "reveal.js": "=4.3.1", "typed-js": "^0.2.3" },