From a7b5a320713ef319a6d9e2ce0f9a494bab5c7751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 11 Mar 2025 01:44:37 +0100 Subject: [PATCH] 0.1.3 (#5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Julien Valverdé Reviewed-on: https://gitea:3000/Thilawyn/reffuse/pulls/5 --- .gitea/workflows/publish.yaml | 7 + README.md | 1 + bun.lock | 146 ++++++++++-------- packages/example/package.json | 28 ++-- packages/example/src/query/reffuse.ts | 10 ++ .../example/src/query/services/Uuid4Query.ts | 12 ++ packages/example/src/query/services/index.ts | 1 + .../src/query/views/Uuid4QueryService.tsx | 32 ++++ packages/example/src/reffuse.ts | 2 + packages/example/src/routeTree.gen.ts | 63 +++++++- packages/example/src/routes/__root.tsx | 1 + packages/example/src/routes/query/service.tsx | 35 +++++ .../example/src/routes/query/usequery.tsx | 66 ++++++++ packages/example/src/routes/tests.tsx | 21 ++- packages/extension-lazyref/README.md | 2 +- packages/extension-lazyref/package.json | 5 +- packages/extension-lazyref/src/index.ts | 10 +- packages/extension-query/README.md | 10 ++ packages/extension-query/package.json | 44 ++++++ .../extension-query/src/QueryExtension.ts | 55 +++++++ packages/extension-query/src/QueryRunner.ts | 144 +++++++++++++++++ packages/extension-query/src/QueryService.ts | 32 ++++ packages/extension-query/src/index.ts | 3 + packages/extension-query/tsconfig.json | 33 ++++ packages/reffuse/package.json | 3 +- packages/reffuse/src/ReffuseContext.tsx | 16 +- packages/reffuse/src/ReffuseHelpers.ts | 29 +++- turbo.json | 5 +- 28 files changed, 707 insertions(+), 109 deletions(-) create mode 100644 packages/example/src/query/reffuse.ts create mode 100644 packages/example/src/query/services/Uuid4Query.ts create mode 100644 packages/example/src/query/services/index.ts create mode 100644 packages/example/src/query/views/Uuid4QueryService.tsx create mode 100644 packages/example/src/routes/query/service.tsx create mode 100644 packages/example/src/routes/query/usequery.tsx create mode 100644 packages/extension-query/README.md create mode 100644 packages/extension-query/package.json create mode 100644 packages/extension-query/src/QueryExtension.ts create mode 100644 packages/extension-query/src/QueryRunner.ts create mode 100644 packages/extension-query/src/QueryService.ts create mode 100644 packages/extension-query/src/index.ts create mode 100644 packages/extension-query/tsconfig.json diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml index 83a6528..b71d10c 100644 --- a/.gitea/workflows/publish.yaml +++ b/.gitea/workflows/publish.yaml @@ -31,3 +31,10 @@ jobs: access: public token: ${{ secrets.NPM_TOKEN }} registry: https://registry.npmjs.org + - name: Publish @reffuse/extension-query + uses: JS-DevTools/npm-publish@v3 + with: + package: packages/extension-query + access: public + token: ${{ secrets.NPM_TOKEN }} + registry: https://registry.npmjs.org diff --git a/README.md b/README.md index 0b644b4..bff34c9 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,5 @@ Reffuse is a [Effect-TS](https://effect.website/) integration for React 19+ with This monorepo contains: - [The `reffuse` library](packages/reffuse) - [`@reffuse/extension-lazyref`, a LazyRef integration for Reffuse](packages/extension-lazyref) +- [`@reffuse/extension-query`, TanStack Query style hooks for Reffuse](packages/extension-query) - [An example project](packges/example) diff --git a/bun.lock b/bun.lock index 14fcfe5..5d880de 100644 --- a/bun.lock +++ b/bun.lock @@ -14,33 +14,35 @@ "name": "@reffuse/example", "version": "0.0.0", "dependencies": { - "@effect/platform": "^0.77.2", - "@effect/platform-browser": "^0.56.2", - "@radix-ui/themes": "^3.2.0", + "@effect/platform": "^0.77.6", + "@effect/platform-browser": "^0.56.6", + "@radix-ui/themes": "^3.2.1", "@reffuse/extension-lazyref": "workspace:*", + "@reffuse/extension-query": "workspace:*", + "@typed/async-data": "^0.13.1", "@typed/id": "^0.17.1", "@typed/lazy-ref": "^0.3.3", - "effect": "^3.13.2", - "lucide-react": "^0.476.0", + "effect": "^3.13.6", + "lucide-react": "^0.477.0", "mobx": "^6.13.6", "reffuse": "workspace:*", }, "devDependencies": { "@eslint/js": "^9.21.0", - "@tanstack/react-router": "^1.111.7", - "@tanstack/router-devtools": "^1.111.7", - "@tanstack/router-plugin": "^1.111.7", + "@tanstack/react-router": "^1.112.7", + "@tanstack/router-devtools": "^1.112.7", + "@tanstack/router-plugin": "^1.112.7", "@thilawyn/thilaschema": "^0.1.4", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", "@vitejs/plugin-react": "^4.3.4", "eslint": "^9.21.0", - "eslint-plugin-react-hooks": "^5.1.0", + "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.19", "globals": "^16.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", - "typescript-eslint": "^8.25.0", + "typescript-eslint": "^8.26.0", "vite": "^6.2.0", }, }, @@ -51,16 +53,32 @@ "reffuse": "workspace:*", }, "peerDependencies": { - "@typed/lazy-ref": "^0.3.3", + "@typed/lazy-ref": "^0.3.0", "@types/react": "^19.0.0", "effect": "^3.13.0", "react": "^19.0.0", - "reffuse": "^0.1.1", + "reffuse": "^0.1.2", + }, + }, + "packages/extension-query": { + "name": "@reffuse/extension-query", + "version": "0.1.0", + "devDependencies": { + "reffuse": "workspace:*", + }, + "peerDependencies": { + "@effect/platform": "^0.77.0", + "@effect/platform-browser": "^0.56.0", + "@typed/async-data": "^0.13.0", + "@types/react": "^19.0.0", + "effect": "^3.13.0", + "react": "^19.0.0", + "reffuse": "^0.1.2", }, }, "packages/reffuse": { "name": "reffuse", - "version": "0.1.1", + "version": "0.1.2", "peerDependencies": { "@types/react": "^19.0.0", "effect": "^3.13.0", @@ -111,9 +129,9 @@ "@babel/types": ["@babel/types@7.26.9", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw=="], - "@effect/platform": ["@effect/platform@0.77.2", "", { "dependencies": { "find-my-way-ts": "^0.1.5", "multipasta": "^0.2.5" }, "peerDependencies": { "effect": "^3.13.2" } }, "sha512-stvroKHJVfjd3XhZJEPUAOgzqu9DH1vnGHIAjfs2ma6Z4qcjVpFXrxa0ZYmwRaWVIFsiADMenkN0I7XrRdAgLw=="], + "@effect/platform": ["@effect/platform@0.77.6", "", { "dependencies": { "find-my-way-ts": "^0.1.5", "multipasta": "^0.2.5" }, "peerDependencies": { "effect": "^3.13.6" } }, "sha512-ghhLNyj/UoQvmp2I29nqngMlAzQB72BhjUKcOA58cUPaUUwNy3K2jmUAzdU6SB3RHIObsX44CM/jXZiYfTv59A=="], - "@effect/platform-browser": ["@effect/platform-browser@0.56.2", "", { "dependencies": { "multipasta": "^0.2.5" }, "peerDependencies": { "@effect/platform": "^0.77.2", "effect": "^3.13.2" } }, "sha512-mzCNipg3FN9/ATPEO7Cc3cLmTF4gtdoQSVVi5RPJzIxXflVHbNmMFSIuFdGp0W3AbrQ20dfF6FGFaRUo3aFHeA=="], + "@effect/platform-browser": ["@effect/platform-browser@0.56.6", "", { "dependencies": { "multipasta": "^0.2.5" }, "peerDependencies": { "@effect/platform": "^0.77.6", "effect": "^3.13.6" } }, "sha512-kD4AtfoC81/de3fdk57gRIsKDezr8Fn8jePzjYVx2nGY/0379wJfTwLIDMEHE03Ekv/61UVLbmApT5Cyor3H/A=="], "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ=="], @@ -327,65 +345,67 @@ "@radix-ui/rect": ["@radix-ui/rect@1.1.0", "", {}, "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="], - "@radix-ui/themes": ["@radix-ui/themes@3.2.0", "", { "dependencies": { "@radix-ui/colors": "^3.0.0", "classnames": "^2.3.2", "radix-ui": "^1.1.2", "react-remove-scroll-bar": "^2.3.8" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-cG/47tfHN9FW1ZoAigd3oUeJaIm591vGtQ97PrhfwS22IJgWhE5h6D0w2m+NVbKRVo8qIWCG+hiWN04MlLoW4A=="], + "@radix-ui/themes": ["@radix-ui/themes@3.2.1", "", { "dependencies": { "@radix-ui/colors": "^3.0.0", "classnames": "^2.3.2", "radix-ui": "^1.1.3", "react-remove-scroll-bar": "^2.3.8" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WJL2YKAGItkunwm3O4cLTFKCGJTfAfF6Hmq7f5bCo1ggqC9qJQ/wfg/25AAN72aoEM1yqXZQ+pslsw48AFR0Xg=="], "@reffuse/example": ["@reffuse/example@workspace:packages/example"], "@reffuse/extension-lazyref": ["@reffuse/extension-lazyref@workspace:packages/extension-lazyref"], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.8", "", { "os": "android", "cpu": "arm" }, "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw=="], + "@reffuse/extension-query": ["@reffuse/extension-query@workspace:packages/extension-query"], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.8", "", { "os": "android", "cpu": "arm64" }, "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.9", "", { "os": "android", "cpu": "arm" }, "sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.9", "", { "os": "android", "cpu": "arm64" }, "sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.8", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.9", "", { "os": "linux", "cpu": "arm" }, "sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.9", "", { "os": "linux", "cpu": "arm" }, "sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw=="], - "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A=="], - "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw=="], + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.9", "", { "os": "linux", "cpu": "none" }, "sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw=="], + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.9", "", { "os": "linux", "cpu": "none" }, "sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.9", "", { "os": "linux", "cpu": "x64" }, "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.9", "", { "os": "linux", "cpu": "x64" }, "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.8", "", { "os": "win32", "cpu": "x64" }, "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.9", "", { "os": "win32", "cpu": "x64" }, "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw=="], "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], "@tanstack/history": ["@tanstack/history@1.99.13", "", {}, "sha512-JMd7USmnp8zV8BRGIjALqzPxazvKtQ7PGXQC7n39HpbqdsmfV2ePCzieO84IvN+mwsTrXErpbjI4BfKCa+ZNCg=="], - "@tanstack/react-router": ["@tanstack/react-router@1.111.7", "", { "dependencies": { "@tanstack/history": "1.99.13", "@tanstack/react-store": "^0.7.0", "@tanstack/router-core": "^1.111.7", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-/hOWy7lPmVfRqbwIy2d9mvVLA6ZC4tbcgLDdMXCNRN93LMsGEHCTrgFADdSL2f/rvhPyHeYxsFazEo9+ktgUiw=="], + "@tanstack/react-router": ["@tanstack/react-router@1.112.7", "", { "dependencies": { "@tanstack/history": "1.99.13", "@tanstack/react-store": "^0.7.0", "@tanstack/router-core": "^1.112.0", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-udThbvP01cXMvMUK5OPayxuR7ib5AtFL2VnbZSnnKS/dHGsk8KRS+qmkyqZBuuOxRkkF2MC3+BdPj2UTZ4UNjQ=="], "@tanstack/react-store": ["@tanstack/react-store@0.7.0", "", { "dependencies": { "@tanstack/store": "0.7.0", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-S/Rq17HaGOk+tQHV/yrePMnG1xbsKZIl/VsNWnNXt4XW+tTY8dTlvpJH2ZQ3GRALsusG5K6Q3unAGJ2pd9W/Ng=="], - "@tanstack/router-core": ["@tanstack/router-core@1.111.7", "", { "dependencies": { "@tanstack/history": "1.99.13", "@tanstack/store": "^0.7.0" } }, "sha512-N3u3HGBNb1k+MvL15CGmE4KFEDy3euU/L3ENXjmzPm8zfpeVjs+Tyk3y0nicAk3MSSboGXVU1po19RATdWnTsg=="], + "@tanstack/router-core": ["@tanstack/router-core@1.112.0", "", { "dependencies": { "@tanstack/history": "1.99.13", "@tanstack/store": "^0.7.0" } }, "sha512-kmpMiBuz17Hxyl+ZO+B6/F98p07NSEmgr2JlZkKXcdupLIBAWqcXw+bjowFXNcTEwe9RWsS/WjAC/bBTftr0rA=="], - "@tanstack/router-devtools": ["@tanstack/router-devtools@1.111.7", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16" }, "peerDependencies": { "@tanstack/react-router": "^1.111.7", "csstype": "^3.0.10", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["csstype"] }, "sha512-xZpiIWy/HBhpYUqUxT1dNUn5smQhWhkgjNlJOATzrm81G5T3l2jEr79XPXqwRndWzu2WKqv1kPkScC0ekRgE7Q=="], + "@tanstack/router-devtools": ["@tanstack/router-devtools@1.112.7", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16" }, "peerDependencies": { "@tanstack/react-router": "^1.112.7", "csstype": "^3.0.10", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["csstype"] }, "sha512-37qpVzYK4JEg/i0CvnbKI2G+OyWai9yLyvnm8UIc9f2yDzVZKJ1qEpnRXhuLdGCL8dmsf7PjhAPmw46YnD3fHQ=="], - "@tanstack/router-generator": ["@tanstack/router-generator@1.111.7", "", { "dependencies": { "@tanstack/virtual-file-routes": "^1.99.0", "prettier": "^3.5.0", "tsx": "^4.19.2", "zod": "^3.24.1" }, "peerDependencies": { "@tanstack/react-router": "^1.111.7" }, "optionalPeers": ["@tanstack/react-router"] }, "sha512-+jHX35iF45NHQvHzXuLgyCILUUTyMl3EeClKNkfdaKLvV1adwGDQr24cSKDQLmNKEDXGTijBI5nX8ntkKo5oyA=="], + "@tanstack/router-generator": ["@tanstack/router-generator@1.112.7", "", { "dependencies": { "@tanstack/virtual-file-routes": "^1.99.0", "prettier": "^3.5.0", "tsx": "^4.19.2", "zod": "^3.24.1" }, "peerDependencies": { "@tanstack/react-router": "^1.112.7" }, "optionalPeers": ["@tanstack/react-router"] }, "sha512-2BlV64vej9T+NnjUEX42BOEKpCnC2dUtfxr9Xz0sQk43fMWtNe+2b1jzPzJZWlu8RjaQ5OK22hL+p7GSpph3Kw=="], - "@tanstack/router-plugin": ["@tanstack/router-plugin@1.111.7", "", { "dependencies": { "@babel/core": "^7.26.8", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.26.8", "@babel/traverse": "^7.26.8", "@babel/types": "^7.26.8", "@tanstack/router-core": "^1.111.7", "@tanstack/router-generator": "^1.111.7", "@tanstack/router-utils": "^1.102.2", "@tanstack/virtual-file-routes": "^1.99.0", "@types/babel__core": "^7.20.5", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6", "babel-dead-code-elimination": "^1.0.9", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.1" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.111.7", "vite": ">=5.0.0 || >=6.0.0", "vite-plugin-solid": "^2.11.2", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-aiT/j2OadGbqEWTZUY53o2UeVQIR11+S1h1Gq6GYxQmD/OjdyK/WiMighBK5zeryeWYG4XeC8eFlXMoyuG0v+g=="], + "@tanstack/router-plugin": ["@tanstack/router-plugin@1.112.7", "", { "dependencies": { "@babel/core": "^7.26.8", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.26.8", "@babel/traverse": "^7.26.8", "@babel/types": "^7.26.8", "@tanstack/router-core": "^1.112.0", "@tanstack/router-generator": "^1.112.7", "@tanstack/router-utils": "^1.102.2", "@tanstack/virtual-file-routes": "^1.99.0", "@types/babel__core": "^7.20.5", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6", "babel-dead-code-elimination": "^1.0.9", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.1" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.112.7", "vite": ">=5.0.0 || >=6.0.0", "vite-plugin-solid": "^2.11.2", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-9m5UfLSWd5T2jOG9O0BWd1WkChalYfkO/zZjnQ+JoyvixbqTUmkXWkbNtMrZSfM/lNQO4HiftPMMflLSGWMrWg=="], "@tanstack/router-utils": ["@tanstack/router-utils@1.102.2", "", { "dependencies": { "@babel/generator": "^7.26.8", "@babel/parser": "^7.26.8", "ansis": "^3.11.0", "diff": "^7.0.0" } }, "sha512-Uwl2nbrxhCzviaHHBLNPhSC/OMpZLdOTxTJndUSsXTzWUP4IoQcVmngaIsxi9iriE3ArC1VXuanUAkfGmimNOQ=="], @@ -395,6 +415,8 @@ "@thilawyn/thilaschema": ["@thilawyn/thilaschema@0.1.4", "https://git.valverde.cloud/api/packages/Thilawyn/npm/%40thilawyn%2Fthilaschema/-/0.1.4/thilaschema-0.1.4.tgz", { "dependencies": { "remeda": "^2.17.0", "type-fest": "^4.26.1" } }, "sha512-o+lFjnRrD8N7kJtToKl+OYvVnOwaCGr1X9yMSX/8Y1n4KopOOGFSA9xqmx+MpMe3okp2Hq3Xu1aGHzFsZWxc2A=="], + "@typed/async-data": ["@typed/async-data@0.13.1", "", { "dependencies": { "@typed/lazy-ref": "^0.3.2", "effect": "^3.11.9" } }, "sha512-rKv3HQtoHeGJwZpEaTL0FAEKfqHcMr/x3GtgkE01p2tJiKjq1eVaPZYpweZEEF/zUutox7DQ14oH85x+ZpPA/Q=="], + "@typed/id": ["@typed/id@0.17.1", "", { "dependencies": { "effect": "^3.11.9" } }, "sha512-+nypUUw6PJWePD1aF1CHY4995hDF3VA9c8EBtp1M+pTnyLBZQIkgKbOKamimnl4U+ZV5I3qC+3q1Y4hpmxT+zw=="], "@typed/lazy-ref": ["@typed/lazy-ref@0.3.3", "", { "dependencies": { "effect": "^3.11.9" } }, "sha512-qJoy01/RFYwWBaWhQBzL3Ow20Q+CPybJ/KJnGNKzyDpRUFcEvd3YSQMqZjRdBZmG2wnEpjedAnlCx9ApvKJIlA=="], @@ -415,21 +437,21 @@ "@types/react-dom": ["@types/react-dom@19.0.4", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.25.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.25.0", "@typescript-eslint/type-utils": "8.25.0", "@typescript-eslint/utils": "8.25.0", "@typescript-eslint/visitor-keys": "8.25.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.26.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.26.0", "@typescript-eslint/type-utils": "8.26.0", "@typescript-eslint/utils": "8.26.0", "@typescript-eslint/visitor-keys": "8.26.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.25.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.25.0", "@typescript-eslint/types": "8.25.0", "@typescript-eslint/typescript-estree": "8.25.0", "@typescript-eslint/visitor-keys": "8.25.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.26.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.26.0", "@typescript-eslint/types": "8.26.0", "@typescript-eslint/typescript-estree": "8.26.0", "@typescript-eslint/visitor-keys": "8.26.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.25.0", "", { "dependencies": { "@typescript-eslint/types": "8.25.0", "@typescript-eslint/visitor-keys": "8.25.0" } }, "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.26.0", "", { "dependencies": { "@typescript-eslint/types": "8.26.0", "@typescript-eslint/visitor-keys": "8.26.0" } }, "sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.25.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.25.0", "@typescript-eslint/utils": "8.25.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.26.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.26.0", "@typescript-eslint/utils": "8.26.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.25.0", "", {}, "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.26.0", "", {}, "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.25.0", "", { "dependencies": { "@typescript-eslint/types": "8.25.0", "@typescript-eslint/visitor-keys": "8.25.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.8.0" } }, "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.26.0", "", { "dependencies": { "@typescript-eslint/types": "8.26.0", "@typescript-eslint/visitor-keys": "8.26.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.25.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.25.0", "@typescript-eslint/types": "8.25.0", "@typescript-eslint/typescript-estree": "8.25.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.26.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.26.0", "@typescript-eslint/types": "8.26.0", "@typescript-eslint/typescript-estree": "8.26.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.25.0", "", { "dependencies": { "@typescript-eslint/types": "8.25.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.26.0", "", { "dependencies": { "@typescript-eslint/types": "8.26.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg=="], "@vitejs/plugin-react": ["@vitejs/plugin-react@4.3.4", "", { "dependencies": { "@babel/core": "^7.26.0", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.2" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug=="], @@ -441,7 +463,7 @@ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "ansis": ["ansis@3.16.0", "", {}, "sha512-sU7d/tfZiYrsIAXbdL/CNZld5bCkruzwT5KmqmadCJYxuLxHAOBjidxD5+iLmN/6xEfjcQq1l7OpsiCBlc4LzA=="], + "ansis": ["ansis@3.17.0", "", {}, "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg=="], "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], @@ -463,7 +485,7 @@ "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "caniuse-lite": ["caniuse-lite@1.0.30001700", "", {}, "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001701", "", {}, "sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -493,9 +515,9 @@ "diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="], - "effect": ["effect@3.13.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-/w+CPqHDJ33Wq7xC4YKAchrEEPtjvxh563xH9kDTZp99seNYBoBs87vl8DJwartEjj+KLQLP8PzoDne+XmGT2A=="], + "effect": ["effect@3.13.6", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-NKmzyIuOb2UuHFPRz9EYScbhMBxXkzjPRuu+4axE+hMk1f0U7TZxzi2CP3TVVxA2kzvh00aBQEbyH7Opq4PnWg=="], - "electron-to-chromium": ["electron-to-chromium@1.5.104", "", {}, "sha512-Us9M2L4cO/zMBqVkJtnj353nQhMju9slHm62NprKTmdF3HH8wYOtNvDFq/JB2+ZRoGLzdvYDiATlMHs98XBM1g=="], + "electron-to-chromium": ["electron-to-chromium@1.5.111", "", {}, "sha512-vJyJlO95wQRAw6K2ZGF/8nol7AcbCOnp8S6H91mwOOBbXoS9seDBYxCTPYAFsvXLxl3lc0jLXXe9GLxC4nXVog=="], "esbuild": ["esbuild@0.25.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.0", "@esbuild/android-arm": "0.25.0", "@esbuild/android-arm64": "0.25.0", "@esbuild/android-x64": "0.25.0", "@esbuild/darwin-arm64": "0.25.0", "@esbuild/darwin-x64": "0.25.0", "@esbuild/freebsd-arm64": "0.25.0", "@esbuild/freebsd-x64": "0.25.0", "@esbuild/linux-arm": "0.25.0", "@esbuild/linux-arm64": "0.25.0", "@esbuild/linux-ia32": "0.25.0", "@esbuild/linux-loong64": "0.25.0", "@esbuild/linux-mips64el": "0.25.0", "@esbuild/linux-ppc64": "0.25.0", "@esbuild/linux-riscv64": "0.25.0", "@esbuild/linux-s390x": "0.25.0", "@esbuild/linux-x64": "0.25.0", "@esbuild/netbsd-arm64": "0.25.0", "@esbuild/netbsd-x64": "0.25.0", "@esbuild/openbsd-arm64": "0.25.0", "@esbuild/openbsd-x64": "0.25.0", "@esbuild/sunos-x64": "0.25.0", "@esbuild/win32-arm64": "0.25.0", "@esbuild/win32-ia32": "0.25.0", "@esbuild/win32-x64": "0.25.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw=="], @@ -505,7 +527,7 @@ "eslint": ["eslint@9.21.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.0", "@eslint/js": "9.21.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg=="], - "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.1.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw=="], + "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="], "eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.19", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ=="], @@ -533,7 +555,7 @@ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - "fastq": ["fastq@1.19.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA=="], + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], @@ -605,7 +627,7 @@ "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - "lucide-react": ["lucide-react@0.476.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-x6cLTk8gahdUPje0hSgLN1/MgiJH+Xl90Xoxy9bkPAsMPOUiyRSKR4JCDPGVCEpyqnZXH3exFWNItcvra9WzUQ=="], + "lucide-react": ["lucide-react@0.477.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-yCf7aYxerFZAbd8jHJxjwe1j7jEMPptjnaOqdYeirFnEy85cNR3/L+o0I875CYFYya+eEVzZSbNuRk8BZPDpVw=="], "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], @@ -651,7 +673,7 @@ "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "prettier": ["prettier@3.5.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg=="], + "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], @@ -677,7 +699,7 @@ "reffuse": ["reffuse@workspace:packages/reffuse"], - "remeda": ["remeda@2.20.2", "", { "dependencies": { "type-fest": "^4.33.0" } }, "sha512-38pfm5aUq6mUkNYbt7TdY2WEk9mSqRVV+6UsoTjabwmbu8obLbh8sYYSX2WQ3W4u6EYp3XxUKqIiwGFZu+OY9g=="], + "remeda": ["remeda@2.21.0", "", { "dependencies": { "type-fest": "^4.35.0" } }, "sha512-ANFqOts3BsvW1MrKOv9SVHG3ly0MzzLa0HIu5qLkiRuEPGPuH9ny3sgd7VdHvC2VOUSN/7RkmabPlAda6JtGgg=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -685,7 +707,7 @@ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - "rollup": ["rollup@4.34.8", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.8", "@rollup/rollup-android-arm64": "4.34.8", "@rollup/rollup-darwin-arm64": "4.34.8", "@rollup/rollup-darwin-x64": "4.34.8", "@rollup/rollup-freebsd-arm64": "4.34.8", "@rollup/rollup-freebsd-x64": "4.34.8", "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", "@rollup/rollup-linux-arm-musleabihf": "4.34.8", "@rollup/rollup-linux-arm64-gnu": "4.34.8", "@rollup/rollup-linux-arm64-musl": "4.34.8", "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", "@rollup/rollup-linux-riscv64-gnu": "4.34.8", "@rollup/rollup-linux-s390x-gnu": "4.34.8", "@rollup/rollup-linux-x64-gnu": "4.34.8", "@rollup/rollup-linux-x64-musl": "4.34.8", "@rollup/rollup-win32-arm64-msvc": "4.34.8", "@rollup/rollup-win32-ia32-msvc": "4.34.8", "@rollup/rollup-win32-x64-msvc": "4.34.8", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ=="], + "rollup": ["rollup@4.34.9", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.9", "@rollup/rollup-android-arm64": "4.34.9", "@rollup/rollup-darwin-arm64": "4.34.9", "@rollup/rollup-darwin-x64": "4.34.9", "@rollup/rollup-freebsd-arm64": "4.34.9", "@rollup/rollup-freebsd-x64": "4.34.9", "@rollup/rollup-linux-arm-gnueabihf": "4.34.9", "@rollup/rollup-linux-arm-musleabihf": "4.34.9", "@rollup/rollup-linux-arm64-gnu": "4.34.9", "@rollup/rollup-linux-arm64-musl": "4.34.9", "@rollup/rollup-linux-loongarch64-gnu": "4.34.9", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.9", "@rollup/rollup-linux-riscv64-gnu": "4.34.9", "@rollup/rollup-linux-s390x-gnu": "4.34.9", "@rollup/rollup-linux-x64-gnu": "4.34.9", "@rollup/rollup-linux-x64-musl": "4.34.9", "@rollup/rollup-win32-arm64-msvc": "4.34.9", "@rollup/rollup-win32-ia32-msvc": "4.34.9", "@rollup/rollup-win32-x64-msvc": "4.34.9", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ=="], "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], @@ -731,15 +753,15 @@ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - "type-fest": ["type-fest@4.35.0", "", {}, "sha512-2/AwEFQDFEy30iOLjrvHDIH7e4HEWH+f1Yl1bI5XMqzuoCUqwYCdxachgsgv0og/JdVZUhbfjcJAoHj5L1753A=="], + "type-fest": ["type-fest@4.36.0", "", {}, "sha512-3T/PUdKTCnkUmhQU6FFJEHsLwadsRegktX3TNHk+2JJB9HlA8gp1/VXblXVDI93kSnXF2rdPx0GMbHtJIV2LPg=="], - "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], + "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], - "typescript-eslint": ["typescript-eslint@8.25.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.25.0", "@typescript-eslint/parser": "8.25.0", "@typescript-eslint/utils": "8.25.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-TxRdQQLH4g7JkoFlYG3caW5v1S6kEkz8rqt80iQJZUYPq1zD1Ra7HfQBJJ88ABRaMvHAXnwRvRB4V+6sQ9xN5Q=="], + "typescript-eslint": ["typescript-eslint@8.26.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.26.0", "@typescript-eslint/parser": "8.26.0", "@typescript-eslint/utils": "8.26.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-PtVz9nAnuNJuAVeUFvwztjuUgSnJInODAUx47VDwWPXzd5vismPOtPtt83tzNXyOjVQbPRp786D6WFW/M2koIA=="], "unplugin": ["unplugin@2.2.0", "", { "dependencies": { "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" } }, "sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw=="], - "update-browserslist-db": ["update-browserslist-db@1.1.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg=="], + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], diff --git a/packages/example/package.json b/packages/example/package.json index e1a234e..08ae5f9 100644 --- a/packages/example/package.json +++ b/packages/example/package.json @@ -12,35 +12,41 @@ }, "devDependencies": { "@eslint/js": "^9.21.0", - "@tanstack/react-router": "^1.111.7", - "@tanstack/router-devtools": "^1.111.7", - "@tanstack/router-plugin": "^1.111.7", + "@tanstack/react-router": "^1.112.7", + "@tanstack/router-devtools": "^1.112.7", + "@tanstack/router-plugin": "^1.112.7", "@thilawyn/thilaschema": "^0.1.4", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", "@vitejs/plugin-react": "^4.3.4", "eslint": "^9.21.0", - "eslint-plugin-react-hooks": "^5.1.0", + "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.19", "globals": "^16.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", - "typescript-eslint": "^8.25.0", + "typescript-eslint": "^8.26.0", "vite": "^6.2.0" }, "dependencies": { - "@effect/platform": "^0.77.2", - "@effect/platform-browser": "^0.56.2", - "@radix-ui/themes": "^3.2.0", + "@effect/platform": "^0.77.6", + "@effect/platform-browser": "^0.56.6", + "@radix-ui/themes": "^3.2.1", "@reffuse/extension-lazyref": "workspace:*", + "@reffuse/extension-query": "workspace:*", + "@typed/async-data": "^0.13.1", "@typed/id": "^0.17.1", "@typed/lazy-ref": "^0.3.3", - "effect": "^3.13.2", - "lucide-react": "^0.476.0", + "effect": "^3.13.6", + "lucide-react": "^0.477.0", "mobx": "^6.13.6", "reffuse": "workspace:*" }, "overrides": { - "effect": "^3.13.2" + "effect": "^3.13.6", + "@effect/platform": "^0.77.6", + "@effect/platform-browser": "^0.56.6", + "@typed/lazy-ref": "^0.3.3", + "@typed/async-data": "^0.13.1" } } diff --git a/packages/example/src/query/reffuse.ts b/packages/example/src/query/reffuse.ts new file mode 100644 index 0000000..ced8e18 --- /dev/null +++ b/packages/example/src/query/reffuse.ts @@ -0,0 +1,10 @@ +import { GlobalReffuse } from "@/reffuse" +import { Reffuse, ReffuseContext } from "reffuse" +import { Uuid4Query } from "./services" + + +export const QueryContext = ReffuseContext.make() + +export const R = new class QueryReffuse extends GlobalReffuse.pipe( + Reffuse.withContexts(QueryContext) +) {} diff --git a/packages/example/src/query/services/Uuid4Query.ts b/packages/example/src/query/services/Uuid4Query.ts new file mode 100644 index 0000000..a7336bd --- /dev/null +++ b/packages/example/src/query/services/Uuid4Query.ts @@ -0,0 +1,12 @@ +import { HttpClientError } from "@effect/platform" +import { QueryService } from "@reffuse/extension-query" +import { ParseResult, Schema } from "effect" + + +export const Result = Schema.Array(Schema.String) + +export class Uuid4Query extends QueryService.Tag("Uuid4Query")() {} diff --git a/packages/example/src/query/services/index.ts b/packages/example/src/query/services/index.ts new file mode 100644 index 0000000..4f67d41 --- /dev/null +++ b/packages/example/src/query/services/index.ts @@ -0,0 +1 @@ +export * as Uuid4Query from "./Uuid4Query" diff --git a/packages/example/src/query/views/Uuid4QueryService.tsx b/packages/example/src/query/views/Uuid4QueryService.tsx new file mode 100644 index 0000000..bc0eada --- /dev/null +++ b/packages/example/src/query/views/Uuid4QueryService.tsx @@ -0,0 +1,32 @@ +import { Button, Container, Flex, Text } from "@radix-ui/themes" +import * as AsyncData from "@typed/async-data" +import { R } from "../reffuse" +import { Uuid4Query } from "../services" + + +export function Uuid4QueryService() { + const runSync = R.useRunSync() + + const query = R.useMemo(() => Uuid4Query.Uuid4Query, []) + const [state] = R.useRefState(query.state) + + + return ( + + + + {AsyncData.match(state, { + NoData: () => "No data yet", + Loading: () => "Loading...", + Success: (value, { isRefreshing, isOptimistic }) => + `Value: ${value} ${isRefreshing ? "(refreshing)" : ""} ${isOptimistic ? "(optimistic)" : ""}`, + Failure: (cause, { isRefreshing }) => + `Error: ${cause} ${isRefreshing ? "(refreshing)" : ""}`, + })} + + + + + + ) +} diff --git a/packages/example/src/reffuse.ts b/packages/example/src/reffuse.ts index 0aefd92..c5d008f 100644 --- a/packages/example/src/reffuse.ts +++ b/packages/example/src/reffuse.ts @@ -1,6 +1,7 @@ import { HttpClient } from "@effect/platform" import { Clipboard, Geolocation, Permissions } from "@effect/platform-browser" import { LazyRefExtension } from "@reffuse/extension-lazyref" +import { QueryExtension } from "@reffuse/extension-query" import { Reffuse, ReffuseContext } from "reffuse" @@ -13,6 +14,7 @@ export const GlobalContext = ReffuseContext.make< export class GlobalReffuse extends Reffuse.Reffuse.pipe( Reffuse.withExtension(LazyRefExtension), + Reffuse.withExtension(QueryExtension), Reffuse.withContexts(GlobalContext), ) {} diff --git a/packages/example/src/routeTree.gen.ts b/packages/example/src/routeTree.gen.ts index 98b4224..8e9816d 100644 --- a/packages/example/src/routeTree.gen.ts +++ b/packages/example/src/routeTree.gen.ts @@ -18,6 +18,8 @@ import { Route as LazyrefImport } from './routes/lazyref' import { Route as CountImport } from './routes/count' import { Route as BlankImport } from './routes/blank' import { Route as IndexImport } from './routes/index' +import { Route as QueryUsequeryImport } from './routes/query/usequery' +import { Route as QueryServiceImport } from './routes/query/service' // Create/Update Routes @@ -63,6 +65,18 @@ const IndexRoute = IndexImport.update({ getParentRoute: () => rootRoute, } as any) +const QueryUsequeryRoute = QueryUsequeryImport.update({ + id: '/query/usequery', + path: '/query/usequery', + getParentRoute: () => rootRoute, +} as any) + +const QueryServiceRoute = QueryServiceImport.update({ + id: '/query/service', + path: '/query/service', + getParentRoute: () => rootRoute, +} as any) + // Populate the FileRoutesByPath interface declare module '@tanstack/react-router' { @@ -116,6 +130,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof TimeImport parentRoute: typeof rootRoute } + '/query/service': { + id: '/query/service' + path: '/query/service' + fullPath: '/query/service' + preLoaderRoute: typeof QueryServiceImport + parentRoute: typeof rootRoute + } + '/query/usequery': { + id: '/query/usequery' + path: '/query/usequery' + fullPath: '/query/usequery' + preLoaderRoute: typeof QueryUsequeryImport + parentRoute: typeof rootRoute + } } } @@ -129,6 +157,8 @@ export interface FileRoutesByFullPath { '/promise': typeof PromiseRoute '/tests': typeof TestsRoute '/time': typeof TimeRoute + '/query/service': typeof QueryServiceRoute + '/query/usequery': typeof QueryUsequeryRoute } export interface FileRoutesByTo { @@ -139,6 +169,8 @@ export interface FileRoutesByTo { '/promise': typeof PromiseRoute '/tests': typeof TestsRoute '/time': typeof TimeRoute + '/query/service': typeof QueryServiceRoute + '/query/usequery': typeof QueryUsequeryRoute } export interface FileRoutesById { @@ -150,6 +182,8 @@ export interface FileRoutesById { '/promise': typeof PromiseRoute '/tests': typeof TestsRoute '/time': typeof TimeRoute + '/query/service': typeof QueryServiceRoute + '/query/usequery': typeof QueryUsequeryRoute } export interface FileRouteTypes { @@ -162,8 +196,19 @@ export interface FileRouteTypes { | '/promise' | '/tests' | '/time' + | '/query/service' + | '/query/usequery' fileRoutesByTo: FileRoutesByTo - to: '/' | '/blank' | '/count' | '/lazyref' | '/promise' | '/tests' | '/time' + to: + | '/' + | '/blank' + | '/count' + | '/lazyref' + | '/promise' + | '/tests' + | '/time' + | '/query/service' + | '/query/usequery' id: | '__root__' | '/' @@ -173,6 +218,8 @@ export interface FileRouteTypes { | '/promise' | '/tests' | '/time' + | '/query/service' + | '/query/usequery' fileRoutesById: FileRoutesById } @@ -184,6 +231,8 @@ export interface RootRouteChildren { PromiseRoute: typeof PromiseRoute TestsRoute: typeof TestsRoute TimeRoute: typeof TimeRoute + QueryServiceRoute: typeof QueryServiceRoute + QueryUsequeryRoute: typeof QueryUsequeryRoute } const rootRouteChildren: RootRouteChildren = { @@ -194,6 +243,8 @@ const rootRouteChildren: RootRouteChildren = { PromiseRoute: PromiseRoute, TestsRoute: TestsRoute, TimeRoute: TimeRoute, + QueryServiceRoute: QueryServiceRoute, + QueryUsequeryRoute: QueryUsequeryRoute, } export const routeTree = rootRoute @@ -212,7 +263,9 @@ export const routeTree = rootRoute "/lazyref", "/promise", "/tests", - "/time" + "/time", + "/query/service", + "/query/usequery" ] }, "/": { @@ -235,6 +288,12 @@ export const routeTree = rootRoute }, "/time": { "filePath": "time.tsx" + }, + "/query/service": { + "filePath": "query/service.tsx" + }, + "/query/usequery": { + "filePath": "query/usequery.tsx" } } } diff --git a/packages/example/src/routes/__root.tsx b/packages/example/src/routes/__root.tsx index e5a9b44..3253372 100644 --- a/packages/example/src/routes/__root.tsx +++ b/packages/example/src/routes/__root.tsx @@ -20,6 +20,7 @@ function Root() { Count Tests Promise + Query Blank diff --git a/packages/example/src/routes/query/service.tsx b/packages/example/src/routes/query/service.tsx new file mode 100644 index 0000000..6a926a8 --- /dev/null +++ b/packages/example/src/routes/query/service.tsx @@ -0,0 +1,35 @@ +import { QueryContext } from "@/query/reffuse" +import { Uuid4Query } from "@/query/services" +import { Uuid4QueryService } from "@/query/views/Uuid4QueryService" +import { R } from "@/reffuse" +import { HttpClient } from "@effect/platform" +import { createFileRoute } from "@tanstack/react-router" +import { Console, Effect, Schema } from "effect" +import { useMemo } from "react" + + +export const Route = createFileRoute("/query/service")({ + component: RouteComponent +}) + +function RouteComponent() { + const query = R.useQuery({ + key: R.useStreamFromValues(["uuid4", 10 as number]), + query: ([, count]) => Console.log(`Querying ${ count } IDs...`).pipe( + Effect.andThen(Effect.sleep("500 millis")), + Effect.andThen(HttpClient.get(`https://www.uuidtools.com/api/generate/v4/count/${ count }`)), + HttpClient.withTracerPropagation(false), + Effect.flatMap(res => res.json), + Effect.flatMap(Schema.decodeUnknown(Uuid4Query.Result)), + Effect.scoped, + ), + }) + + const layer = useMemo(() => query.layer(Uuid4Query.Uuid4Query), [query]) + + return ( + + + + ) +} diff --git a/packages/example/src/routes/query/usequery.tsx b/packages/example/src/routes/query/usequery.tsx new file mode 100644 index 0000000..1f76770 --- /dev/null +++ b/packages/example/src/routes/query/usequery.tsx @@ -0,0 +1,66 @@ +import { R } from "@/reffuse" +import { HttpClient } from "@effect/platform" +import { Button, Container, Flex, Slider, Text } from "@radix-ui/themes" +import { createFileRoute } from "@tanstack/react-router" +import * as AsyncData from "@typed/async-data" +import { Array, Console, Effect, flow, Option, Schema } from "effect" +import { useState } from "react" + + +export const Route = createFileRoute("/query/usequery")({ + component: RouteComponent +}) + + +const Result = Schema.Array(Schema.String) + +function RouteComponent() { + const runSync = R.useRunSync() + + const [count, setCount] = useState(1) + + const query = R.useQuery({ + key: R.useStreamFromValues(["uuid4", count]), + query: ([, count]) => Console.log(`Querying ${ count } IDs...`).pipe( + Effect.andThen(Effect.sleep("500 millis")), + Effect.andThen(HttpClient.get(`https://www.uuidtools.com/api/generate/v4/count/${ count }`)), + HttpClient.withTracerPropagation(false), + Effect.flatMap(res => res.json), + Effect.flatMap(Schema.decodeUnknown(Result)), + Effect.scoped, + ), + }) + + const [state] = R.useRefState(query.state) + + + return ( + + + + + + {AsyncData.match(state, { + NoData: () => "No data yet", + Loading: () => "Loading...", + Success: (value, { isRefreshing, isOptimistic }) => + `Value: ${value} ${isRefreshing ? "(refreshing)" : ""} ${isOptimistic ? "(optimistic)" : ""}`, + Failure: (cause, { isRefreshing }) => + `Error: ${cause} ${isRefreshing ? "(refreshing)" : ""}`, + })} + + + + + + ) +} diff --git a/packages/example/src/routes/tests.tsx b/packages/example/src/routes/tests.tsx index 93e791e..884b5f7 100644 --- a/packages/example/src/routes/tests.tsx +++ b/packages/example/src/routes/tests.tsx @@ -1,7 +1,9 @@ import { R } from "@/reffuse" -import { Button } from "@radix-ui/themes" +import { Button, Flex } from "@radix-ui/themes" import { createFileRoute } from "@tanstack/react-router" -import { Console, Effect } from "effect" +import { GetRandomValues, makeUuid4 } from "@typed/id" +import { Console, Effect, Stream } from "effect" +import { useState } from "react" export const Route = createFileRoute("/tests")({ @@ -20,12 +22,25 @@ function RouteComponent() { Effect.delay("1 second"), ), []) + const [reactValue, setReactValue] = useState("initial") + const reactValueStream = R.useStreamFromValues([reactValue]) + R.useFork(() => Stream.runForEach(reactValueStream, Console.log), [reactValueStream]) + + const logValue = R.useCallbackSync(Effect.fn(function*(value: string) { yield* Effect.log(value) }), []) + const generateUuid = R.useCallbackSync(() => makeUuid4.pipe( + Effect.provide(GetRandomValues.CryptoRandom), + Effect.map(setReactValue), + ), []) + return ( - + + + + ) } diff --git a/packages/extension-lazyref/README.md b/packages/extension-lazyref/README.md index 699855e..fcf0a16 100644 --- a/packages/extension-lazyref/README.md +++ b/packages/extension-lazyref/README.md @@ -4,6 +4,6 @@ Extension to integrate `@typed/lazy-ref` with Reffuse. ## Peer dependencies - `@typed/lazy-ref` -- `reffuse` 0.1.2+ +- `reffuse` 0.1.3+ - `effect` 3.13+ - `react` & `@types/react` 19+ diff --git a/packages/extension-lazyref/package.json b/packages/extension-lazyref/package.json index 055bae6..5b921aa 100644 --- a/packages/extension-lazyref/package.json +++ b/packages/extension-lazyref/package.json @@ -25,7 +25,6 @@ "build": "tsc", "lint:tsc": "tsc --noEmit", "pack": "npm pack", - "publish": "npm publish --access public", "clean:cache": "rm -f tsconfig.tsbuildinfo", "clean:dist": "rm -rf dist", "clean:node": "rm -rf node_modules" @@ -34,10 +33,10 @@ "reffuse": "workspace:*" }, "peerDependencies": { - "@typed/lazy-ref": "^0.3.3", + "@typed/lazy-ref": "^0.3.0", "@types/react": "^19.0.0", "effect": "^3.13.0", "react": "^19.0.0", - "reffuse": "^0.1.2" + "reffuse": "^0.1.3" } } diff --git a/packages/extension-lazyref/src/index.ts b/packages/extension-lazyref/src/index.ts index e5fbb02..18e6aef 100644 --- a/packages/extension-lazyref/src/index.ts +++ b/packages/extension-lazyref/src/index.ts @@ -9,19 +9,17 @@ export const LazyRefExtension = ReffuseExtension.make(() => ({ this: ReffuseHelpers.ReffuseHelpers, ref: LazyRef.LazyRef, ): [A, React.Dispatch>] { - const runSync = this.useRunSync() - - const initialState = React.useMemo(() => runSync(ref), []) + const initialState = this.useMemo(() => ref, [], { doNotReExecuteOnRuntimeOrContextChange: true }) const [reactStateValue, setReactStateValue] = React.useState(initialState) this.useFork(() => Stream.runForEach(ref.changes, v => Effect.sync(() => setReactStateValue(v) )), [ref]) - const setValue = React.useCallback((setStateAction: React.SetStateAction) => - runSync(LazyRef.update(ref, prevState => + const setValue = this.useCallbackSync((setStateAction: React.SetStateAction) => + LazyRef.update(ref, prevState => SetStateAction.value(setStateAction, prevState) - )), + ), [ref]) return [reactStateValue, setValue] diff --git a/packages/extension-query/README.md b/packages/extension-query/README.md new file mode 100644 index 0000000..e9fd209 --- /dev/null +++ b/packages/extension-query/README.md @@ -0,0 +1,10 @@ +# Reffuse Query + +TanStack Query style hooks for Reffuse. + +## Peer dependencies +- `reffuse` 0.1.3+ +- `effect` 3.13+ +- `@effect/platform` & `@effect/platform-browser` +- `react` & `@types/react` 19+ +- `@typed/async-data` diff --git a/packages/extension-query/package.json b/packages/extension-query/package.json new file mode 100644 index 0000000..a41819c --- /dev/null +++ b/packages/extension-query/package.json @@ -0,0 +1,44 @@ +{ + "name": "@reffuse/extension-query", + "version": "0.1.0", + "type": "module", + "files": [ + "./README.md", + "./dist" + ], + "license": "MIT", + "repository": { + "url": "git+https://github.com/Thiladev/reffuse.git" + }, + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./*": { + "types": "./dist/*.d.ts", + "default": "./dist/*.js" + } + }, + "scripts": { + "build": "tsc", + "lint:tsc": "tsc --noEmit", + "pack": "npm pack", + "clean:cache": "rm -f tsconfig.tsbuildinfo", + "clean:dist": "rm -rf dist", + "clean:node": "rm -rf node_modules" + }, + "devDependencies": { + "reffuse": "workspace:*" + }, + "peerDependencies": { + "@effect/platform": "^0.77.0", + "@effect/platform-browser": "^0.56.0", + "@typed/async-data": "^0.13.0", + "@types/react": "^19.0.0", + "effect": "^3.13.0", + "react": "^19.0.0", + "reffuse": "^0.1.3" + } +} diff --git a/packages/extension-query/src/QueryExtension.ts b/packages/extension-query/src/QueryExtension.ts new file mode 100644 index 0000000..79c0a89 --- /dev/null +++ b/packages/extension-query/src/QueryExtension.ts @@ -0,0 +1,55 @@ +import type * as AsyncData from "@typed/async-data" +import { type Cause, type Context, Effect, type Fiber, Layer, type Option, type Stream, type SubscriptionRef } from "effect" +import * as React from "react" +import { ReffuseExtension, type ReffuseHelpers } from "reffuse" +import * as QueryRunner from "./QueryRunner.js" +import type * as QueryService from "./QueryService.js" + + +export interface UseQueryProps { + readonly key: Stream.Stream + readonly query: (key: K) => Effect.Effect + readonly refreshOnWindowFocus?: boolean +} + +export interface UseQueryResult { + readonly latestKey: SubscriptionRef.SubscriptionRef> + readonly state: SubscriptionRef.SubscriptionRef> + readonly refresh: Effect.Effect> + + readonly layer: ( + tag: Context.TagClass> + ) => Layer.Layer +} + + +export const QueryExtension = ReffuseExtension.make(() => ({ + useQuery( + this: ReffuseHelpers.ReffuseHelpers, + props: UseQueryProps, + ): UseQueryResult { + const runner = this.useMemo(() => QueryRunner.make({ + key: props.key, + query: props.query, + }), [props.key]) + + this.useFork(() => runner.fetchOnKeyChange, [runner]) + + this.useFork(() => (props.refreshOnWindowFocus ?? true) + ? runner.refreshOnWindowFocus + : Effect.void, + [props.refreshOnWindowFocus, runner]) + + return React.useMemo(() => ({ + latestKey: runner.latestKeyRef, + state: runner.stateRef, + refresh: runner.forkRefresh, + + layer: tag => Layer.succeed(tag, { + latestKey: runner.latestKeyRef, + state: runner.stateRef, + refresh: runner.forkRefresh, + }), + }), [runner]) + } +})) diff --git a/packages/extension-query/src/QueryRunner.ts b/packages/extension-query/src/QueryRunner.ts new file mode 100644 index 0000000..a403672 --- /dev/null +++ b/packages/extension-query/src/QueryRunner.ts @@ -0,0 +1,144 @@ +import { BrowserStream } from "@effect/platform-browser" +import * as AsyncData from "@typed/async-data" +import { type Cause, Effect, Fiber, identity, Option, Ref, type Scope, Stream, SubscriptionRef } from "effect" + + +export interface QueryRunner { + readonly query: (key: K) => Effect.Effect + + readonly latestKeyRef: SubscriptionRef.SubscriptionRef> + readonly stateRef: SubscriptionRef.SubscriptionRef> + readonly fiberRef: SubscriptionRef.SubscriptionRef>> + + readonly forkInterrupt: Effect.Effect> + readonly forkFetch: Effect.Effect> + readonly forkRefresh: Effect.Effect> + + readonly fetchOnKeyChange: Effect.Effect + readonly refreshOnWindowFocus: Effect.Effect +} + + +export interface MakeProps { + readonly key: Stream.Stream + readonly query: (key: K) => Effect.Effect +} + +export const make = ( + { key, query }: MakeProps +): Effect.Effect, never, R> => Effect.gen(function*() { + const context = yield* Effect.context() + + const latestKeyRef = yield* SubscriptionRef.make(Option.none()) + const stateRef = yield* SubscriptionRef.make(AsyncData.noData()) + const fiberRef = yield* SubscriptionRef.make(Option.none>()) + + const interrupt = fiberRef.pipe( + Effect.flatMap(Option.match({ + onSome: fiber => Ref.set(fiberRef, Option.none()).pipe( + Effect.andThen(Fiber.interrupt(fiber)) + ), + onNone: () => Effect.void, + })) + ) + + const forkInterrupt = fiberRef.pipe( + Effect.flatMap(Option.match({ + onSome: fiber => Ref.set(fiberRef, Option.none()).pipe( + Effect.andThen(Fiber.interrupt(fiber).pipe( + Effect.asVoid, + Effect.forkDaemon, + )) + ), + onNone: () => Effect.forkDaemon(Effect.void), + })) + ) + + const forkFetch = interrupt.pipe( + Effect.andThen( + Ref.set(stateRef, AsyncData.loading()).pipe( + Effect.andThen(latestKeyRef), + Effect.flatMap(identity), + Effect.flatMap(key => query(key).pipe( + Effect.matchCauseEffect({ + onSuccess: v => Ref.set(stateRef, AsyncData.success(v)), + onFailure: c => Ref.set(stateRef, AsyncData.failure(c)), + }) + )), + + Effect.provide(context), + Effect.fork, + ) + ), + + Effect.flatMap(fiber => + Ref.set(fiberRef, Option.some(fiber)).pipe( + Effect.andThen(Fiber.join(fiber)), + Effect.andThen(Ref.set(fiberRef, Option.none())), + ) + ), + + Effect.forkDaemon, + ) + + const forkRefresh = interrupt.pipe( + Effect.andThen( + Ref.update(stateRef, previous => { + if (AsyncData.isSuccess(previous) || AsyncData.isFailure(previous)) + return AsyncData.refreshing(previous) + if (AsyncData.isRefreshing(previous)) + return AsyncData.refreshing(previous.previous) + return AsyncData.loading() + }).pipe( + Effect.andThen(latestKeyRef), + Effect.flatMap(identity), + Effect.flatMap(key => query(key).pipe( + Effect.matchCauseEffect({ + onSuccess: v => Ref.set(stateRef, AsyncData.success(v)), + onFailure: c => Ref.set(stateRef, AsyncData.failure(c)), + }) + )), + + Effect.provide(context), + Effect.fork, + ) + ), + + Effect.flatMap(fiber => + Ref.set(fiberRef, Option.some(fiber)).pipe( + Effect.andThen(Fiber.join(fiber)), + Effect.andThen(Ref.set(fiberRef, Option.none())), + ) + ), + + Effect.forkDaemon, + ) + + const fetchOnKeyChange = Effect.addFinalizer(() => interrupt).pipe( + Effect.andThen(Stream.runForEach(key, latestKey => + Ref.set(latestKeyRef, Option.some(latestKey)).pipe( + Effect.andThen(forkFetch) + ) + )) + ) + + const refreshOnWindowFocus = Stream.runForEach( + BrowserStream.fromEventListenerWindow("focus"), + () => forkRefresh, + ) + + return { + query, + + latestKeyRef, + stateRef, + fiberRef, + + forkInterrupt, + forkFetch, + forkRefresh, + + fetchOnKeyChange, + refreshOnWindowFocus, + } +}) diff --git a/packages/extension-query/src/QueryService.ts b/packages/extension-query/src/QueryService.ts new file mode 100644 index 0000000..33fce17 --- /dev/null +++ b/packages/extension-query/src/QueryService.ts @@ -0,0 +1,32 @@ +import type * as AsyncData from "@typed/async-data" +import { type Cause, Effect, type Fiber, type Option, type SubscriptionRef } from "effect" + + +export interface QueryService { + readonly latestKey: SubscriptionRef.SubscriptionRef> + readonly state: SubscriptionRef.SubscriptionRef> + readonly refresh: Effect.Effect> +} + +export const Tag = (id: Id) => < + Self, K extends readonly unknown[], A, E = never, +>() => Effect.Tag(id)>() + + +// export interface LayerProps { +// readonly query: Effect.Effect +// } + +// export const layer = ( +// tag: Context.TagClass>, +// props: LayerProps, +// ): Layer.Layer => Layer.effect(tag, Effect.gen(function*() { +// const runner = yield* QueryRunner.make({ +// query: props.query +// }) + +// return { +// state: runner.stateRef, +// refresh: runner.forkRefresh, +// } +// })) diff --git a/packages/extension-query/src/index.ts b/packages/extension-query/src/index.ts new file mode 100644 index 0000000..790fe0c --- /dev/null +++ b/packages/extension-query/src/index.ts @@ -0,0 +1,3 @@ +export * from "./QueryExtension.js" +export * as QueryRunner from "./QueryRunner.js" +export * as QueryService from "./QueryService.js" diff --git a/packages/extension-query/tsconfig.json b/packages/extension-query/tsconfig.json new file mode 100644 index 0000000..eea16a8 --- /dev/null +++ b/packages/extension-query/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "NodeNext", + "moduleDetection": "force", + "jsx": "react-jsx", + // "allowJs": true, + + // Bundler mode + "moduleResolution": "NodeNext", + // "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + // "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false, + + // Build + "outDir": "./dist", + "declaration": true + }, + + "include": ["./src"] +} diff --git a/packages/reffuse/package.json b/packages/reffuse/package.json index 842c01d..bfe88f7 100644 --- a/packages/reffuse/package.json +++ b/packages/reffuse/package.json @@ -1,6 +1,6 @@ { "name": "reffuse", - "version": "0.1.2", + "version": "0.1.3", "type": "module", "files": [ "./README.md", @@ -25,7 +25,6 @@ "build": "tsc", "lint:tsc": "tsc --noEmit", "pack": "npm pack", - "publish": "npm publish --access public", "clean:cache": "rm -f tsconfig.tsbuildinfo", "clean:dist": "rm -rf dist", "clean:node": "rm -rf node_modules" diff --git a/packages/reffuse/src/ReffuseContext.tsx b/packages/reffuse/src/ReffuseContext.tsx index f1898ff..89d1394 100644 --- a/packages/reffuse/src/ReffuseContext.tsx +++ b/packages/reffuse/src/ReffuseContext.tsx @@ -97,15 +97,15 @@ export function useMergeAll>( return React.useMemo(() => Context.mergeAll(...values), values) } -export function useMergeAllLayers>( +export function useMergeAllLayers>( ...contexts: [...{ [K in keyof T]: ReffuseContext }] ): Layer.Layer { - const values = Array.map( - contexts as Array.NonEmptyArray>, - v => React.use(v.Context), - ) + const values = contexts.map(v => React.use(v.Context)) - return React.useMemo(() => Layer.mergeAll( - ...Array.map(values, context => Layer.effectContext(Effect.succeed(context))) - ), values) + return React.useMemo(() => Array.isNonEmptyArray(values) + ? Layer.mergeAll( + ...Array.map(values, context => Layer.effectContext(Effect.succeed(context))) + ) + : Layer.empty as Layer.Layer, + values) } diff --git a/packages/reffuse/src/ReffuseHelpers.ts b/packages/reffuse/src/ReffuseHelpers.ts index 6b8e5df..2f4f449 100644 --- a/packages/reffuse/src/ReffuseHelpers.ts +++ b/packages/reffuse/src/ReffuseHelpers.ts @@ -1,4 +1,4 @@ -import { type Context, Effect, ExecutionStrategy, Exit, type Fiber, Pipeable, Ref, Runtime, Scope, Stream, SubscriptionRef } from "effect" +import { type Context, Effect, ExecutionStrategy, Exit, type Fiber, type Layer, Pipeable, Queue, Ref, Runtime, Scope, Stream, SubscriptionRef } from "effect" import * as React from "react" import * as ReffuseContext from "./ReffuseContext.js" import * as ReffuseRuntime from "./ReffuseRuntime.js" @@ -23,6 +23,10 @@ export abstract class ReffuseHelpers { return ReffuseContext.useMergeAll(...this.constructor.contexts) } + useLayer(this: ReffuseHelpers): Layer.Layer { + return ReffuseContext.useMergeAllLayers(...this.constructor.contexts) + } + useRunSync(this: ReffuseHelpers): (effect: Effect.Effect) => A { const runtime = ReffuseRuntime.useRuntime() @@ -388,23 +392,34 @@ export abstract class ReffuseHelpers { this: ReffuseHelpers, ref: SubscriptionRef.SubscriptionRef, ): [A, React.Dispatch>] { - const runSync = this.useRunSync() - - const initialState = React.useMemo(() => runSync(ref), []) + const initialState = this.useMemo(() => ref, [], { doNotReExecuteOnRuntimeOrContextChange: true }) const [reactStateValue, setReactStateValue] = React.useState(initialState) this.useFork(() => Stream.runForEach(ref.changes, v => Effect.sync(() => setReactStateValue(v) )), [ref]) - const setValue = React.useCallback((setStateAction: React.SetStateAction) => - runSync(Ref.update(ref, prevState => + const setValue = this.useCallbackSync((setStateAction: React.SetStateAction) => + Ref.update(ref, prevState => SetStateAction.value(setStateAction, prevState) - )), + ), [ref]) return [reactStateValue, setValue] } + + useStreamFromValues( + this: ReffuseHelpers, + values: A, + ): Stream.Stream { + const [queue, stream] = this.useMemo(() => Queue.unbounded().pipe( + Effect.map(queue => [queue, Stream.fromQueue(queue)] as const) + ), []) + + this.useEffect(() => Queue.offer(queue, values), values) + + return stream + } } diff --git a/turbo.json b/turbo.json index 010d736..2ce9ea7 100644 --- a/turbo.json +++ b/turbo.json @@ -6,9 +6,6 @@ "inputs": ["./src/**"], "outputs": ["./dist/**"] }, - "pack": {}, - "publish": { - "passThroughEnv": ["NODE_AUTH_TOKEN"] - } + "pack": {} } }