diff --git a/bun.lock b/bun.lock index 736180a..0ef16db 100644 --- a/bun.lock +++ b/bun.lock @@ -215,11 +215,11 @@ "@effect/experimental": ["@effect/experimental@0.43.1", "", { "dependencies": { "msgpackr": "^1.10.2", "uuid": "^11.0.3" }, "peerDependencies": { "@effect/platform": "^0.79.1", "@effect/platform-node": "^0.75.1", "effect": "^3.13.10", "ioredis": "^5", "lmdb": "^3", "ws": "^8" }, "optionalPeers": ["@effect/platform-node", "ioredis", "lmdb", "ws"] }, "sha512-d0PjBA2EYWoroiA161IM7OF4vIsgIlPuVzTdM2sPvsLc0g+U056YQi4qMAWThrnswGzzI7arsIqIn6kMorcyBg=="], - "@effect/platform": ["@effect/platform@0.79.1", "", { "dependencies": { "find-my-way-ts": "^0.1.5", "multipasta": "^0.2.5" }, "peerDependencies": { "effect": "^3.13.10" } }, "sha512-kCoeBuQrdMuEigcuXk9eDoL9WiFIlLlLZeQZj/LapxC3kgnw/6BViJsRQm+Iqei7Z+zRr930suMpdX75CujCXA=="], + "@effect/platform": ["@effect/platform@0.79.3", "", { "dependencies": { "find-my-way-ts": "^0.1.5", "multipasta": "^0.2.5" }, "peerDependencies": { "effect": "^3.13.12" } }, "sha512-oABDV66SmrUVP+xWL/a+WPvz53m8ckNkv9Cgk09rhOXgzL3eusjDj8VFaIzz0OPgInjRTRoMVemILW0voTYjYA=="], "@effect/sql": ["@effect/sql@0.32.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.25.1", "uuid": "^11.0.3" }, "peerDependencies": { "@effect/experimental": "^0.43.1", "@effect/platform": "^0.79.1", "effect": "^3.13.10" } }, "sha512-dYBfH+q9RlC70lY2gWNzQHHUCjsL8hj+w5f/scIxaenrVZqH1rdMPPS8T8OtoMyh0MU8mD4bkc4bhbd6MPC95Q=="], - "@effect/sql-drizzle": ["@effect/sql-drizzle@0.31.1", "", { "peerDependencies": { "@effect/sql": "^0.32.1", "drizzle-orm": "^0.31", "effect": "^3.13.10" } }, "sha512-1Ko+BMRwTPxnA/lnVVUFr+4nuCOuZ6WxSRy4rl3wXp9vVbGThFaoKqDl27/eSDrszaLZ/Itlp3ArGlurqV4IpQ=="], + "@effect/sql-drizzle": ["@effect/sql-drizzle@0.31.3", "", { "peerDependencies": { "@effect/sql": "^0.32.3", "drizzle-orm": "^0.31", "effect": "^3.13.12" } }, "sha512-PxDhJK95ETBefkyc5pyFfAHBHx/8ELlRzP/tq7bBUltfbA89ciKW6m3FmfQlHMeVhp6ji/aeql6APL6h7u5TSg=="], "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], @@ -375,55 +375,55 @@ "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], - "@thi.ng/api": ["@thi.ng/api@8.11.22", "", {}, "sha512-SbgnYcuyIKvJF+bdpFNZJxggYa6wBt7xh4OjWZwvmbZvibrjvk4xwLaJ8vm/bJoBYK/Oe631CApssa6kumZeNg=="], + "@thi.ng/api": ["@thi.ng/api@8.11.23", "", {}, "sha512-IOIhn+pWEDHZeE0sKWlj2Mz4KW3GO5b0+zmDESPyFLJhW1DVbEUPuzXM8qsVyRVJWvoyZaJpSIcRB7/nEWg8lA=="], - "@thi.ng/arrays": ["@thi.ng/arrays@2.10.19", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/checks": "^3.7.2", "@thi.ng/compare": "^2.4.14", "@thi.ng/equiv": "^2.1.78", "@thi.ng/errors": "^2.5.28", "@thi.ng/random": "^4.1.13" } }, "sha512-wC1Jkvej8zDfSXZmIGp6qMg452mjt4BExMWSaVqaLbMKYszGLgMHJAa8PTUfHrK5A2wQXn35uZwpVbWd+jeubA=="], + "@thi.ng/arrays": ["@thi.ng/arrays@2.10.20", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/checks": "^3.7.3", "@thi.ng/compare": "^2.4.15", "@thi.ng/equiv": "^2.1.79", "@thi.ng/errors": "^2.5.29", "@thi.ng/random": "^4.1.14" } }, "sha512-fWluanYD/nvdoaS+XUCqR9r4iTxaVaNWN0fOFGjXnBQ11oZHvxPM2CmDmS4Y78V80aXcwoTx272r036c4oa0GA=="], - "@thi.ng/base-n": ["@thi.ng/base-n@2.7.34", "", {}, "sha512-LX7X9uaFIedAtDwzt6PzzaiHRPYGRjdVuAmhDV5bl8oB1SBfGaaj4PVumNbXkvKoelijl77oO6RspppVgE8/+Q=="], + "@thi.ng/base-n": ["@thi.ng/base-n@2.7.35", "", {}, "sha512-moKYUF0FTvQVXC34kTIXnBce235OhKDkYOx35NZzw8XKjDBEYqkiCmmW44CyXXMcXnKGq9sZZvnCqpM32/FRgQ=="], - "@thi.ng/binary": ["@thi.ng/binary@3.4.45", "", { "dependencies": { "@thi.ng/api": "^8.11.22" } }, "sha512-VsLh3/zVWk+lquCDw90kIhZdS+VqBeSQyK29KVW66rQ7JAGn1glDhJuaqrucK/NEGnXmqxJfZqJdcEEJsn7M/Q=="], + "@thi.ng/binary": ["@thi.ng/binary@3.4.46", "", { "dependencies": { "@thi.ng/api": "^8.11.23" } }, "sha512-zuZ3qwPXHWL4m3NH93014Ah0oEpIR2kx1/LeZ5c9JFtEVPLgQ3F4rhkjyPOe83+h/F6jpzKxeNXNML7zDkWQiw=="], - "@thi.ng/canvas": ["@thi.ng/canvas@1.0.9", "", {}, "sha512-BptFGkpJBi92IbHKyOmuoRr6M1yRoNReiM8a6lJOXtPwGQAowIAZX3HI/LBYp8jwwnyA/G3adXVoT6wfUqmwgw=="], + "@thi.ng/canvas": ["@thi.ng/canvas@1.0.10", "", {}, "sha512-ry+JwVlnq6SjkHGJf+ycsyHhkhst9D5+HcbUcZ3JfQexY84nRlZpdzNd7Tc5sGAsJoZk+MeKjwdiZXLd+lzgnQ=="], - "@thi.ng/checks": ["@thi.ng/checks@3.7.2", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-FGFHQrLOUKxLoNQfaoVKW8xBhFNaxtV0QqREbxYgnpCg8WgX5O8dU/T212bVTOMe0GSzqCkjEs3/BmPb4lxW5Q=="], + "@thi.ng/checks": ["@thi.ng/checks@3.7.3", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-FxvhMfNFljyPYWphdl+pi9MABih1K95tGAM72vh/TVtkBsl2w+iw4Scje2eI3kBhSc0Vr8rqiDLBV+Ka9c7KvQ=="], - "@thi.ng/color": ["@thi.ng/color@5.7.28", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/arrays": "^2.10.19", "@thi.ng/binary": "^3.4.45", "@thi.ng/checks": "^3.7.2", "@thi.ng/compare": "^2.4.14", "@thi.ng/compose": "^3.0.25", "@thi.ng/defmulti": "^3.0.62", "@thi.ng/errors": "^2.5.28", "@thi.ng/math": "^5.11.22", "@thi.ng/random": "^4.1.13", "@thi.ng/strings": "^3.9.7", "@thi.ng/transducers": "^9.2.22", "@thi.ng/vectors": "^7.12.24" } }, "sha512-NreMb8WrUXcFMg33m3AmtW8638H9VOVB2kzuy1FqrHL/xQJnNFMsgingEt2ts8uZxKb0dlBBZJfx+u10SmNPlA=="], + "@thi.ng/color": ["@thi.ng/color@5.7.29", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/arrays": "^2.10.20", "@thi.ng/binary": "^3.4.46", "@thi.ng/checks": "^3.7.3", "@thi.ng/compare": "^2.4.15", "@thi.ng/compose": "^3.0.26", "@thi.ng/defmulti": "^3.0.63", "@thi.ng/errors": "^2.5.29", "@thi.ng/math": "^5.11.23", "@thi.ng/random": "^4.1.14", "@thi.ng/strings": "^3.9.8", "@thi.ng/transducers": "^9.2.23", "@thi.ng/vectors": "^7.12.25" } }, "sha512-M9tWw+Zi7fT/79PTUI0/BV+1d7YSVsLYuBerlWY+iI10csfgy99jVOLUQBIsBOFlUZ8NnovDLNdkrQ+p3HPCOg=="], - "@thi.ng/color-palettes": ["@thi.ng/color-palettes@1.4.37", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/base-n": "^2.7.34", "@thi.ng/checks": "^3.7.2", "@thi.ng/color": "^5.7.28", "@thi.ng/errors": "^2.5.28", "@thi.ng/hex": "^2.3.66" } }, "sha512-NKoAnWJ3QEJYDUGzxCiBuIkiJplqtb6s+hRkLW8KD6Xw5klv9ajeBVxj93NY/4qB92Q0npfNWXCIrff++JM04A=="], + "@thi.ng/color-palettes": ["@thi.ng/color-palettes@1.4.38", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/base-n": "^2.7.35", "@thi.ng/checks": "^3.7.3", "@thi.ng/color": "^5.7.29", "@thi.ng/errors": "^2.5.29", "@thi.ng/hex": "^2.3.67" } }, "sha512-2l3MJNYK7AmhKvmehm0/VxWKyTadLhan/tzpVJtFwAqIhdmyKgI87xpGLP3phj8GNaVYyKjzthl2/QrIyxUe0Q=="], - "@thi.ng/compare": ["@thi.ng/compare@2.4.14", "", { "dependencies": { "@thi.ng/api": "^8.11.22" } }, "sha512-w/Bu2kNWVM94/BYYTB7QdNrd8UEKz/Wfv6w6ZZjdTGJ/69MrT+8m6jqnCeloD+WjkQ3vsfexLhRUmOft+fTrzQ=="], + "@thi.ng/compare": ["@thi.ng/compare@2.4.15", "", { "dependencies": { "@thi.ng/api": "^8.11.23" } }, "sha512-O/SAqv91CNC63eOrxswJoHWzpIGHBeDuHDJkMbSIlmV4HHQrA4oDUuHYQpsG1XZp9ODWV9+67aYvKLMLsbqz6Q=="], - "@thi.ng/compose": ["@thi.ng/compose@3.0.25", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/errors": "^2.5.28" } }, "sha512-PAni1jk2b444GwGM+GLs++xeuOZ3OzJ6bVW+xr2D6iutLuqHsySFN2v44yTaWSVf1jxP0yqHla8en84b5ko92A=="], + "@thi.ng/compose": ["@thi.ng/compose@3.0.26", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/errors": "^2.5.29" } }, "sha512-alYJT7LaEnZdgFcAbqZaQotU9eypS6KBXDmkYJl8gDGXmEWtjylm1NLvtEBXFJQZXEqp/xObYPmKsGdeu37n6A=="], - "@thi.ng/defmulti": ["@thi.ng/defmulti@3.0.62", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/errors": "^2.5.28", "@thi.ng/logger": "^3.1.3" } }, "sha512-38sYjdjl7JFZPEPCRIay1mEHhbXK61iNExkOmJ6Qw2m9fzO0uT9NJ9CkH/iMnyNLfx1nTvZQwo48Q9qVkGMufQ=="], + "@thi.ng/defmulti": ["@thi.ng/defmulti@3.0.63", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/errors": "^2.5.29", "@thi.ng/logger": "^3.1.4" } }, "sha512-b9EoGxoY09ejtKRwX68cywojS6F8ioG6qgphBsA02hj9rcgr0CzYscT3APbDC1fxmrgELueOb4SxuoiZ9Ezwdw=="], - "@thi.ng/equiv": ["@thi.ng/equiv@2.1.78", "", {}, "sha512-dEyGSzf/62Fv9X9swfqFfsB2/zWOQK+ItlwIarUXWxijYUIw0smCca4oix+eWs4/2QnESV1p0I1Jp66d8Psydg=="], + "@thi.ng/equiv": ["@thi.ng/equiv@2.1.79", "", {}, "sha512-g88vufD8UR+BelK62PD2XG2pgCrC+zEQEmvZpuDMX2cVA+ZMFRPqI1l4JdNHvCYAlu3j6+ZETT66+/SzkRVtjw=="], - "@thi.ng/errors": ["@thi.ng/errors@2.5.28", "", {}, "sha512-ZYFe7Hq9Oh2e2mOxlTc22/btCkozb0tm0xNAKK5kOoU8BxByh2fnN/qK1rHOfx11TW6EYtMpfEMQDdjmclOwjw=="], + "@thi.ng/errors": ["@thi.ng/errors@2.5.29", "", {}, "sha512-MxdWCd6wNYGDurhTOyuUi7iEurYgRq5GPaTTieCGq4J52tpqPpFW35flDoz/2slpWwukxPPhPSQRc45B7X77SQ=="], - "@thi.ng/hex": ["@thi.ng/hex@2.3.66", "", {}, "sha512-X4YVOByqPZYjIlqdDoZOpzNGW8FF5T2yWuAP3j80RPkVsgX2BM+gQYPyY7kkDe3gzWaRJIYE2TIwFHM+0RogJw=="], + "@thi.ng/hex": ["@thi.ng/hex@2.3.67", "", {}, "sha512-uxEjcbZYAqG060jidIxkwHWNe1bhXx/pY1s+P/j+chxRQYINOGivsx7uUsEhkDmoFUiCOxs/PD29/t2E6hLIDA=="], - "@thi.ng/logger": ["@thi.ng/logger@3.1.3", "", {}, "sha512-UOxnYsAeVyvPQuT1bcnZJGm5lRhHRYq1oJ08nISOy1lMoluN0Cht5jqGZVCG03hqwXj1sSsfhk6u08H4W5ACCQ=="], + "@thi.ng/logger": ["@thi.ng/logger@3.1.4", "", {}, "sha512-6i+22+a4g8vbP0KN1/qQyxZd39TCOfME1R2zGycXQ7qSJpnvLMgM6Rvzxc6I1dcSDhCDlLd4KGr07P4B1ERd0w=="], - "@thi.ng/math": ["@thi.ng/math@5.11.22", "", { "dependencies": { "@thi.ng/api": "^8.11.22" } }, "sha512-HpYCjOAZWfpiaGd4dVYrqYI8MbnOCpJWBDCUmGIienNCNnjov4iwmsHhi52kVCEIz3bDJtaEkPqB6L663wvCSw=="], + "@thi.ng/math": ["@thi.ng/math@5.11.23", "", { "dependencies": { "@thi.ng/api": "^8.11.23" } }, "sha512-rsRNYtH84T83IIT6IW6BpiuH7f1mGWwUrSAt2Cy5X/cYniH/GemP3rs2Fe3XsOhblUcJsy/mWyzs93stAoiafw=="], - "@thi.ng/memoize": ["@thi.ng/memoize@4.0.12", "", { "dependencies": { "@thi.ng/api": "^8.11.22" } }, "sha512-fVNaCojN+thuWstM+/Dz6iPOlH1MJD4yHx+pLErfkJjStAH1UGRCZt2C05qJrSDy8KJxNRfxcQivPKiJClzMCg=="], + "@thi.ng/memoize": ["@thi.ng/memoize@4.0.13", "", { "dependencies": { "@thi.ng/api": "^8.11.23" } }, "sha512-CNPxEJeUXyVRlMUTRyLpROrCnVCqMt6nCLmGPEI8GMVnTsw9uxA9Q1sDXHgKQGSGrEnyKx1Qgm6wgnYEd2hhiQ=="], - "@thi.ng/pixel": ["@thi.ng/pixel@7.3.20", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/canvas": "^1.0.9", "@thi.ng/checks": "^3.7.2", "@thi.ng/errors": "^2.5.28", "@thi.ng/math": "^5.11.22", "@thi.ng/porter-duff": "^2.1.100" } }, "sha512-n6CEMda8XYSrItk/llWlbV5GhFVBwWD9peTgXu/uL6BiZrTtrNmuO19hNiOALo/yWIFmWgb36eeSh0AFr6+d6w=="], + "@thi.ng/pixel": ["@thi.ng/pixel@7.4.1", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/canvas": "^1.0.10", "@thi.ng/checks": "^3.7.3", "@thi.ng/errors": "^2.5.29", "@thi.ng/math": "^5.11.23", "@thi.ng/porter-duff": "^2.1.101" } }, "sha512-d4INw8VXQnDxmOqviMbTexQdTE8uxLkpMthl7ori3F9YzhaYKMj+O6Kjmx6M8Jz4bgPrsj6tHFkPOWP70uhPSg=="], - "@thi.ng/pixel-dither": ["@thi.ng/pixel-dither@1.1.160", "", { "dependencies": { "@thi.ng/checks": "^3.7.2", "@thi.ng/math": "^5.11.22", "@thi.ng/pixel": "^7.3.20" } }, "sha512-3VDO050krFIxiQ8LpwPqFlhyXzVe7upzApPWhIwGyJI2bAs9exqxLU1lrDLG9kqx0R17ktHr22NFOgOWra5iyQ=="], + "@thi.ng/pixel-dither": ["@thi.ng/pixel-dither@1.1.162", "", { "dependencies": { "@thi.ng/checks": "^3.7.3", "@thi.ng/math": "^5.11.23", "@thi.ng/pixel": "^7.4.1" } }, "sha512-D83VSKsHdy98VYHLqLKnC2pUh0uNt054Nk8/CPVTsBf8zaeUBKgi0Nfzuo2ELJu5ek8VcQ7QdSbSGC/s2iKn4A=="], - "@thi.ng/porter-duff": ["@thi.ng/porter-duff@2.1.100", "", { "dependencies": { "@thi.ng/api": "^8.11.22" } }, "sha512-qkaYL2KySvBBmjPzNvR/mMXO71NEg7grc/TKfTQijArtZdvg5odsjAI+FJXrb2ArrleXqXZKsO3dMdeD3t51ZQ=="], + "@thi.ng/porter-duff": ["@thi.ng/porter-duff@2.1.101", "", { "dependencies": { "@thi.ng/api": "^8.11.23" } }, "sha512-7c5ci0C/VTHsJiZEMRlMefpL/SGrBD8Ea/5Tr+u7e3Zi6XSKhU3gjXS9wh18QXYaX83CadhaN28pbeRAUzS/2g=="], - "@thi.ng/random": ["@thi.ng/random@4.1.13", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/errors": "^2.5.28" } }, "sha512-FQXVYRLt98hItEpzLrGaG7EUuP6+bJYvXeQ65NjtC0pGf+x/DxubI8Jmqphr5EyH8odyxuDzxdnRbak+p3Dnyg=="], + "@thi.ng/random": ["@thi.ng/random@4.1.14", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/errors": "^2.5.29" } }, "sha512-BqdPkfV6t7STKFX3df2bAs/STGGcXQdBxQtdCSNlxMghXAxPS4TjF6tbS5UY7+UMfd2fM3N/Ez4bxqrqka8giA=="], - "@thi.ng/strings": ["@thi.ng/strings@3.9.7", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/errors": "^2.5.28", "@thi.ng/hex": "^2.3.66", "@thi.ng/memoize": "^4.0.12" } }, "sha512-J1cNbtSaYCiuTYJJE4rFHsnJIMVKKyjGLcBoGMPUTK40uiR+rwM7Rg3nIbalW7QcBfcNejAelHFzHO5aTD3u3w=="], + "@thi.ng/strings": ["@thi.ng/strings@3.9.8", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/errors": "^2.5.29", "@thi.ng/hex": "^2.3.67", "@thi.ng/memoize": "^4.0.13" } }, "sha512-5CgV1t+0IMlrHkcuMI3AbBVSBjSD6bDnl6PRo7jAr1H6D0I/uvc9cSFLcruXrofVwt7PnfeNAdjeDzbra0gXXw=="], - "@thi.ng/timestamp": ["@thi.ng/timestamp@1.1.7", "", {}, "sha512-puu4cA5HqBoNeRpgPgKdwDHo6YI1PoS9S/X6HiMDfWVhv6Ln4SzydduvJF7fpCEs/01xtMu/8wSpGHH1icBdaA=="], + "@thi.ng/timestamp": ["@thi.ng/timestamp@1.1.8", "", {}, "sha512-SFuDMRV2yLIZoHK4Hn/lXZ6aX4RE14k2ZfjK2ba/TWxfx7pSRMVM6zzF1FlRkxQ08bFfkPEy6eLsFdWasoJMfA=="], - "@thi.ng/transducers": ["@thi.ng/transducers@9.2.22", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/arrays": "^2.10.19", "@thi.ng/checks": "^3.7.2", "@thi.ng/compare": "^2.4.14", "@thi.ng/compose": "^3.0.25", "@thi.ng/errors": "^2.5.28", "@thi.ng/math": "^5.11.22", "@thi.ng/random": "^4.1.13", "@thi.ng/timestamp": "^1.1.7" } }, "sha512-CFYXYRlGsRKUZdroQkEn09HagzXhIhs73jVcJ8ld05O8L+H2Y3RPgsOEcSd/ysB1oH/2LfVuFbYkNXg/1jvlDQ=="], + "@thi.ng/transducers": ["@thi.ng/transducers@9.2.23", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/arrays": "^2.10.20", "@thi.ng/checks": "^3.7.3", "@thi.ng/compare": "^2.4.15", "@thi.ng/compose": "^3.0.26", "@thi.ng/errors": "^2.5.29", "@thi.ng/math": "^5.11.23", "@thi.ng/random": "^4.1.14", "@thi.ng/timestamp": "^1.1.8" } }, "sha512-cekzk5OATrN+br4xdJ2AY5T74SJBCdbhZCrFG+JLZo0jauU8yFsSVMUzvXZWQDqSUbwSBLNI10IOSOY2hEzVAA=="], - "@thi.ng/vectors": ["@thi.ng/vectors@7.12.24", "", { "dependencies": { "@thi.ng/api": "^8.11.22", "@thi.ng/binary": "^3.4.45", "@thi.ng/checks": "^3.7.2", "@thi.ng/equiv": "^2.1.78", "@thi.ng/errors": "^2.5.28", "@thi.ng/math": "^5.11.22", "@thi.ng/memoize": "^4.0.12", "@thi.ng/random": "^4.1.13", "@thi.ng/strings": "^3.9.7", "@thi.ng/transducers": "^9.2.22" } }, "sha512-ZxwlnDb/TZBR57BN0bcqFmZfQDu7NCNUBXO/LRhKAPVoqTXyShxELUYhFWKV8oNF8Tr7+dcJUg46tg9pP6VMtA=="], + "@thi.ng/vectors": ["@thi.ng/vectors@7.12.25", "", { "dependencies": { "@thi.ng/api": "^8.11.23", "@thi.ng/binary": "^3.4.46", "@thi.ng/checks": "^3.7.3", "@thi.ng/equiv": "^2.1.79", "@thi.ng/errors": "^2.5.29", "@thi.ng/math": "^5.11.23", "@thi.ng/memoize": "^4.0.13", "@thi.ng/random": "^4.1.14", "@thi.ng/strings": "^3.9.8", "@thi.ng/transducers": "^9.2.23" } }, "sha512-bc2OkRIif78xSFLAw9JPNqboiNAiDt6YIO783RLBowSJ9Wc0LEn5cEgwH4MZ7xJzR/bKC9VeZ03zX79KEr9oug=="], "@types/bun": ["@types/bun@1.2.5", "", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="], @@ -455,7 +455,7 @@ "@ungap/with-resolvers": ["@ungap/with-resolvers@0.1.0", "", {}, "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw=="], - "@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.1", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ=="], + "@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.3", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg=="], "@volar/language-core": ["@volar/language-core@2.4.12", "", { "dependencies": { "@volar/source-map": "2.4.12" } }, "sha512-RLrFdXEaQBWfSnYGVxvR2WrO6Bub0unkdHYIdC31HzIEqATIuuhRRzYu76iGPZ6OtA4Au1SnW0ZwIqPP217YhA=="], @@ -481,7 +481,7 @@ "@vue/eslint-config-typescript": ["@vue/eslint-config-typescript@14.5.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.26.0", "fast-glob": "^3.3.3", "typescript-eslint": "^8.26.0", "vue-eslint-parser": "^10.1.1" }, "peerDependencies": { "eslint": "^9.10.0", "eslint-plugin-vue": "^9.28.0 || ^10.0.0", "typescript": ">=4.8.4" }, "optionalPeers": ["typescript"] }, "sha512-5oPOyuwkw++AP5gHDh5YFmST50dPfWOcm3/W7Nbh42IK5O3H74ytWAw0TrCRTaBoD/02khnWXuZf1Bz1xflavQ=="], - "@vue/language-core": ["@vue/language-core@2.2.8", "", { "dependencies": { "@volar/language-core": "~2.4.11", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^1.0.3", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-rrzB0wPGBvcwaSNRriVWdNAbHQWSf0NlGqgKHK5mEkXpefjUlVRP62u03KvwZpvKVjRnBIQ/Lwre+Mx9N6juUQ=="], + "@vue/language-core": ["@vue/language-core@3.0.0-alpha.2", "", { "dependencies": { "@volar/language-core": "~2.4.11", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^1.0.3", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-GFbo3BM7sxkSNSZVz6+Pq3f/sEyRspGb+7Sqoxnm/rCjPtFOklcIADakhXFN4VmKgwOO1mfjCzuvTkZORv3BMw=="], "@vue/reactivity": ["@vue/reactivity@3.5.13", "", { "dependencies": { "@vue/shared": "3.5.13" } }, "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg=="], @@ -493,7 +493,7 @@ "@vue/shared": ["@vue/shared@3.5.13", "", {}, "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="], - "@vue/typescript-plugin": ["@vue/typescript-plugin@2.2.8", "", { "dependencies": { "@volar/typescript": "~2.4.11", "@vue/language-core": "2.2.8", "@vue/shared": "^3.5.0" } }, "sha512-9fzhFYrzIsPm5Qylv6yBmV1tISqkUhE1PD5uBwkeLCxIwNUjIbnGBdN8HszDa1ZWFWuBsbQpx7FxmV7vQincDw=="], + "@vue/typescript-plugin": ["@vue/typescript-plugin@3.0.0-alpha.2", "", { "dependencies": { "@volar/typescript": "~2.4.11", "@vue/language-core": "3.0.0-alpha.2", "@vue/shared": "^3.5.0" } }, "sha512-uzkw4VWk3cXN/XPRd7txh/gJQ5jjv2bQ5mz6fDH/Y5bo2Z6/28ZIZSTIfPyXlFh5y1/IY2G/UwrEJzsrcK25aQ=="], "@xstate/vue": ["@xstate/vue@4.0.2", "", { "peerDependencies": { "vue": "^3.0.0", "xstate": "^5.19.2" }, "optionalPeers": ["xstate"] }, "sha512-2d5/1nEfd3AGMkYoJJPI2uQ9qFKKnpTl5NCLo3utNAKzPsK/9k0cp/FijqtZOxmnHC407qmwErZs1n6u5yBkcQ=="], @@ -627,11 +627,11 @@ "drizzle-kit": ["drizzle-kit@0.30.5", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0", "gel": "^2.0.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-l6dMSE100u7sDaTbLczibrQZjA35jLsHNqIV+jmhNVO3O8jzM6kywMOmV9uOz9ZVSCMPQhAZEFjL/qDPVrqpUA=="], - "drizzle-orm": ["drizzle-orm@0.40.0", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-7ptk/HQiMSrEZHnAsSlBESXWj52VwgMmyTEfoNmpNN2ZXpcz13LwHfXTIghsAEud7Z5UJhDOp8U07ujcqme7wg=="], + "drizzle-orm": ["drizzle-orm@0.40.1", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-aPNhtiJiPfm3qxz1czrnIDkfvkSdKGXYeZkpG55NPTVI186LmK2fBLMi4dsHpPHlJrZeQ92D322YFPHADBALew=="], "easy-table": ["easy-table@1.2.0", "", { "dependencies": { "ansi-regex": "^5.0.1" }, "optionalDependencies": { "wcwidth": "^1.0.1" } }, "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww=="], - "effect": ["effect@3.13.10", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-f2n51BJJ25G9rb/C1ClkgsVFXH6YTkCHmd6ebpu6cAkwQxfhnfbkVWKgkn3nyW9YnC9z4K8bGohRYaZ+HyWtLg=="], + "effect": ["effect@3.13.12", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-XHvZA8lOX7vxk+ME3Q+4BN6EVYsyo8csdHmHsD4oYEtWPb2Ou3WPkpavlHOD+DNap8QIwfZjmDtshcGlgV34hA=="], "electron-to-chromium": ["electron-to-chromium@1.5.116", "", {}, "sha512-mufxTCJzLBQVvSdZzX1s5YAuXsN1M4tTyYxOOL1TcSKtIzQ9rjIrm7yFK80rN5dwGTePgdoABDSHpuVtRQh0Zw=="], @@ -1071,7 +1071,7 @@ "vue-router": ["vue-router@4.5.0", "", { "dependencies": { "@vue/devtools-api": "^6.6.4" }, "peerDependencies": { "vue": "^3.2.0" } }, "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w=="], - "vue-tsc": ["vue-tsc@2.2.8", "", { "dependencies": { "@volar/typescript": "~2.4.11", "@vue/language-core": "2.2.8" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "./bin/vue-tsc.js" } }, "sha512-jBYKBNFADTN+L+MdesNX/TB3XuDSyaWynKMDgR+yCSln0GQ9Tfb7JS2lr46s2LiFUT1WsmfWsSvIElyxzOPqcQ=="], + "vue-tsc": ["vue-tsc@3.0.0-alpha.2", "", { "dependencies": { "@volar/typescript": "~2.4.11", "@vue/language-core": "3.0.0-alpha.2" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "./bin/vue-tsc.js" } }, "sha512-bUCZ/NbEykG7zSE4t3fN7SwKAzDmUieehn2PwYQK5CAA2C9y+kXEt/5Y06ZrymP6wMRsuFFgZpF3H1V2j4UVOA=="], "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], diff --git a/cfg/drizzle.config.ts b/cfg/drizzle.config.ts index 06188ee..f7cb1b9 100644 --- a/cfg/drizzle.config.ts +++ b/cfg/drizzle.config.ts @@ -6,4 +6,5 @@ const DrizzleKitConfig: Config = { schema: "./src/db/schemas.ts", }; + export default DrizzleKitConfig; diff --git a/cspell.json b/cspell.json index 2f818f7..bb32e76 100644 --- a/cspell.json +++ b/cspell.json @@ -18,6 +18,7 @@ "labelledby", "imdb", "xstate", - "ARGB" + "ARGB", + "REWATCH" ] } diff --git a/package.json b/package.json index 58b7284..ea3adf9 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,15 @@ "type": "module", "private": true, "dependencies": { - "@effect/platform": "^0.79.1", - "@effect/sql-drizzle": "^0.31.1", - "@thi.ng/color-palettes": "^1.4.37", - "@thi.ng/pixel": "^7.3.20", - "@thi.ng/pixel-dither": "^1.1.160", + "@effect/platform": "^0.79.3", + "@effect/sql-drizzle": "^0.31.3", + "@thi.ng/color-palettes": "^1.4.38", + "@thi.ng/pixel": "^7.4.1", + "@thi.ng/pixel-dither": "^1.1.162", "@xstate/vue": "^4.0.2", "a11y-dialog": "^8.1.1", - "drizzle-orm": "^0.40.0", - "effect": "^3.13.10", + "drizzle-orm": "^0.40.1", + "effect": "^3.13.12", "pinia": "^3.0.1", "sqlocal": "^0.14.0", "vue": "^3.5.13", @@ -23,9 +23,9 @@ "@cspell/dict-fr-fr": "^2.2.5", "@eslint/css": "^0.5.0", "@types/bun": "^1.2.5", - "@vitejs/plugin-vue": "^5.2.1", + "@vitejs/plugin-vue": "^5.2.3", "@vue/eslint-config-typescript": "^14.5.0", - "@vue/typescript-plugin": "^2.2.8", + "@vue/typescript-plugin": "3.0.0-alpha.2", "browserslist": "^4.24.4", "cspell": "^8.17.5", "drizzle-kit": "^0.30.5", @@ -48,6 +48,6 @@ "tsr": "^1.3.4", "typescript": "^5.8.2", "vite": "^6.2.2", - "vue-tsc": "^2.2.8" + "vue-tsc": "3.0.0-alpha.2" } } diff --git a/public/icons/docomo-broken-heart.gif b/public/icons/docomo-broken-heart.gif new file mode 100644 index 0000000..5f6cdab Binary files /dev/null and b/public/icons/docomo-broken-heart.gif differ diff --git a/public/icons/docomo-heart.gif b/public/icons/docomo-heart.gif new file mode 100644 index 0000000..54ec03a Binary files /dev/null and b/public/icons/docomo-heart.gif differ diff --git a/public/icons/docomo-ok.gif b/public/icons/docomo-ok.gif new file mode 100644 index 0000000..a0d8b1d Binary files /dev/null and b/public/icons/docomo-ok.gif differ diff --git a/src/components/dialogs/EditEntryDialog.vue b/src/components/dialogs/EditEntryDialog.vue index 0ad2dbd..f6ca6f8 100644 --- a/src/components/dialogs/EditEntryDialog.vue +++ b/src/components/dialogs/EditEntryDialog.vue @@ -9,12 +9,10 @@ import LoadingBox from "@/components/loading/LoadingBox.vue"; import { getMainMovieCrew } from "@/libs/apis/tmdb/crew"; import { generateDitheredBufferFromUrl } from "@/libs/utils/images"; - import { Images } from "@/services/images.ts"; import { PrettyLogger } from "@/services/logger"; import { RuntimeClient } from "@/services/runtime-client"; import { TmdbApi } from "@/services/tmdb-api"; import { useEntryStore } from "@/stores/entry.ts"; - import { Url } from "@effect/platform"; import { canvasFromPixelBuffer } from "@thi.ng/pixel"; import { Effect, pipe } from "effect"; import { isNotNull } from "effect/Predicate"; diff --git a/src/components/entries/AddDiaryEntryForm.vue b/src/components/entries/AddDiaryEntryForm.vue new file mode 100644 index 0000000..8c9a606 --- /dev/null +++ b/src/components/entries/AddDiaryEntryForm.vue @@ -0,0 +1,176 @@ + + + + + + + + diff --git a/src/db/schemas/constants.ts b/src/db/schemas/constants.ts index f3adf28..4a062a9 100644 --- a/src/db/schemas/constants.ts +++ b/src/db/schemas/constants.ts @@ -19,13 +19,20 @@ export const DIARY_ENTRY_STATES = { WATCHED: "watched", } as const; +export const DIARY_ENTRY_STATES_LABELS = { + DROPPED: "Abandonné", + TO_FIND: "À trouver", + TO_REWATCH: "À re-regarder", + TO_WATCH: "À regarder", + UNKNOWN: "Inconnu", + WATCHED: "Regardé", +} as const; + export const APPRECIATION_STATES = { /** Oeuvre appréciée. */ APPRECIATED: "appreciated", /** Oeuvre non appréciée (détestée). */ DISLIKED: "disliked", - /** Oeuvre laissant de marbre. */ + /** Oeuvre laissant de marbre (valeur par défaut). */ NEUTRAL: "neutral", - /** Appréciation inconnue. */ - UNKNOWN: "unknown", } as const; diff --git a/src/db/schemas/entries.ts b/src/db/schemas/entries.ts index 4d422c2..47e6749 100644 --- a/src/db/schemas/entries.ts +++ b/src/db/schemas/entries.ts @@ -35,7 +35,15 @@ export const DiaryEntriesStates = table("diary_entries_states", { export const Viewings = table("viewings", { artWorkId: t.integer("art_work_id").references((): AnySQLiteColumn => ArtWorks.id).notNull(), - date: t.integer("date", { mode: "timestamp" }).notNull(), + dateViewed: t.integer("date_viewed", { mode: "timestamp" }).notNull(), + id: t.integer("id").primaryKey({ autoIncrement: true }), + location: t.text("location").notNull(), +}); + +export const Media = table("media", { + artWorkId: t.integer("art_work_id").references((): AnySQLiteColumn => ArtWorks.id).notNull(), + dateCreated: t.integer("date_created", { mode: "timestamp" }).notNull(), + dateModified: t.integer("date_modified", { mode: "timestamp" }).notNull(), id: t.integer("id").primaryKey({ autoIncrement: true }), }); @@ -68,7 +76,8 @@ export type DiaryEntryState = Schema.Schema.Type; export const ViewingSchema = Schema.Struct({ artWorkId: Schema.NonNegativeInt, - date: Schema.Number, + dateViewed: Schema.Number, id: Schema.NonNegativeInt, + location: Schema.NonEmptyString, }); export type Viewing = Schema.Schema.Type; diff --git a/src/libs/apis/tmdb/countries.ts b/src/libs/apis/tmdb/countries.ts new file mode 100644 index 0000000..d71e346 --- /dev/null +++ b/src/libs/apis/tmdb/countries.ts @@ -0,0 +1,15 @@ +import { Array as Arr, Option, pipe } from "effect"; + +import type { TmdbCompany } from "./schemas/companies.ts"; + +import { ISO_3166_1_ALPHA_2 } from "./constants.ts"; + +export const getCountryNameFromCompany = (company: TmdbCompany): Option.Option => + Arr.findFirst(ISO_3166_1_ALPHA_2, iso => iso.code === company.origin_country).pipe(Option.map(iso => iso.name)); + +export const getCountriesFromCompanies = (companies: readonly TmdbCompany[]) => + pipe( + Arr.map(companies, (company: TmdbCompany): Option.Option => getCountryNameFromCompany(company)), + Option.all, + Option.andThen((companies: string[]): string[] => Arr.dedupe(companies)), + ); diff --git a/src/libs/apis/tmdb/languages.ts b/src/libs/apis/tmdb/languages.ts new file mode 100644 index 0000000..043d540 --- /dev/null +++ b/src/libs/apis/tmdb/languages.ts @@ -0,0 +1,6 @@ +import { Array as Arr } from "effect"; + +import type { TmdbLanguage } from "./schemas/languages.ts"; + +export const getLanguagesFromSpokenLanguages = (languages: readonly TmdbLanguage[]) => + Arr.map(languages, (language: TmdbLanguage) => language.english_name); diff --git a/src/libs/apis/tmdb/schemas.ts b/src/libs/apis/tmdb/schemas.ts index 921fc31..e87174d 100644 --- a/src/libs/apis/tmdb/schemas.ts +++ b/src/libs/apis/tmdb/schemas.ts @@ -1,12 +1,12 @@ import { Schema } from "effect"; -import { TmdbCompany } from "./schemas/companies"; -import { TmdbCredit } from "./schemas/credits"; -import { DateFromTmdbDate } from "./schemas/dates"; -import { TmdbGenre } from "./schemas/genres"; -import { LanguageIsoCode, TmdbLanguage } from "./schemas/languages"; -import { DurationMinutes, MonetaryAmount } from "./schemas/units"; -import { ArtWorkTitle } from "./schemas/works"; +import { TmdbCompany } from "./schemas/companies.ts"; +import { TmdbCredit } from "./schemas/credits.ts"; +import { DateFromTmdbDate } from "./schemas/dates.ts"; +import { TmdbGenre, TmdbGenreId } from "./schemas/genres.ts"; +import { LanguageIsoCode, TmdbLanguage } from "./schemas/languages.ts"; +import { DurationMinutes, MonetaryAmount } from "./schemas/units.ts"; +import { ArtWorkTitle } from "./schemas/works.ts"; // Requête @@ -46,7 +46,7 @@ export class TmdbMovieSearchResponseResult extends Schema.Class("TmdbMovieSearchResponseResult")({ adult: Schema.Boolean, backdrop_path: Schema.Union(Schema.String, Schema.Null), - genre_ids: Schema.Array(Schema.NonNegativeInt), + genre_ids: Schema.Array(Schema.NonNegativeInt.pipe(Schema.fromBrand(TmdbGenreId))), id: Schema.NonNegativeInt, original_language: Schema.String.pipe(Schema.fromBrand(LanguageIsoCode)), original_title: Schema.String.pipe(Schema.fromBrand(ArtWorkTitle)), diff --git a/src/libs/errors/types.ts b/src/libs/errors/types.ts new file mode 100644 index 0000000..04beb64 --- /dev/null +++ b/src/libs/errors/types.ts @@ -0,0 +1,17 @@ +import { Brand, Schema, String } from "effect"; + +export type ErrorCode = Brand.Brand<"ErrorCode"> & string; +export const ErrorCode = Brand.refined( + (code: string) => String.isString(code), + (code: string) => Brand.error(`${code} n'est pas un code d'erreur valide.`), +); + +export const DisplayErrorSchema = Schema.Struct({ + /** La cause de l'erreur, généralement sous forme d'Error (optionnel). */ + cause: Schema.Unknown.pipe(Schema.optional), + /** Le code d'erreur. */ + code: Schema.NonEmptyString.pipe(Schema.fromBrand(ErrorCode)), + /** Le message lié à l'erreur. */ + message: Schema.NonEmptyString, +}); +export type DisplayError = Schema.Schema.Type; diff --git a/src/libs/forms/types.ts b/src/libs/forms/types.ts new file mode 100644 index 0000000..ef3f4d9 --- /dev/null +++ b/src/libs/forms/types.ts @@ -0,0 +1,18 @@ +import { APPRECIATION_STATES, DIARY_ENTRY_STATES } from "@/db/schemas.ts"; +import { Schema } from "effect"; + +export const AddDiaryEntryFormSchema = Schema.Struct({ + appreciation: Schema.Enums(APPRECIATION_STATES).annotations({ + message: () => "L'appréciation doit être une valeur valide.", + title: "Appreciation", + }), + commentary: Schema.String, + dateObtained: Schema.Unknown.pipe(Schema.optional), + state: Schema.Enums(DIARY_ENTRY_STATES) + .annotations({ + message: () => "Le statut de l'entrée doit être une valeur valide.", + title: "State", + }) + .pipe(Schema.filter(s => s !== DIARY_ENTRY_STATES.UNKNOWN || "L'état de l'entrée doit être choisi.")), +}); +export type AddDiaryEntryForm = Schema.Schema.Type; diff --git a/src/libs/search/schemas.ts b/src/libs/search/schemas.ts index 6a5851e..207b3b4 100644 --- a/src/libs/search/schemas.ts +++ b/src/libs/search/schemas.ts @@ -3,7 +3,7 @@ import { APPRECIATION_STATES, MEDIA_TYPES } from "@/db/schemas/constants"; import { Schema } from "effect"; import { YearString } from "../apis/tmdb/schemas/dates"; -import { TmdbGenre } from "../apis/tmdb/schemas/genres"; +import { TmdbGenreId } from "../apis/tmdb/schemas/genres"; import { LanguageIsoCode } from "../apis/tmdb/schemas/languages"; import { ArtWorkTitle } from "../apis/tmdb/schemas/works"; @@ -14,7 +14,7 @@ export class SearchPageQueryParams extends Schema.Class(" }) {} export class MergedTmdbDataDiaryEntry extends Schema.Class("MergedTmdbDataDiaryEntry")({ - artWorkGenres: Schema.Array(GenreSchema), + artWorkGenres: Schema.Array(GenreSchema).pipe(Schema.optional), artWorkId: Schema.NonNegativeInt.pipe(Schema.optional), artWorkMediumTypeId: Schema.NonNegativeInt.pipe(Schema.optional), entryAppreciation: Schema.Enums(APPRECIATION_STATES).pipe(Schema.optional), @@ -33,6 +33,6 @@ export class MergedTmdbDataDiaryEntry extends Schema.Class; error: { code: string; message: string } }, + input: {} as { entryState: Values }, + }, +}) + .createMachine({ + context: ({ input }) => ({ + entryState: input.entryState, + error: { + code: "", + message: "", + }, + }), + }); diff --git a/src/pages/AddEntryPage.vue b/src/pages/AddEntryPage.vue index a84bd16..82d5d81 100644 --- a/src/pages/AddEntryPage.vue +++ b/src/pages/AddEntryPage.vue @@ -3,7 +3,10 @@ import type { TmdbGenreName } from "@/libs/apis/tmdb/schemas/genres.ts"; import type { ArtWorkTitle } from "@/libs/apis/tmdb/schemas/works.ts"; + import AddDiaryEntryForm from "@/components/entries/AddDiaryEntryForm.vue"; + import { getCountriesFromCompanies } from "@/libs/apis/tmdb/countries.ts"; import { getMainMovieCrew } from "@/libs/apis/tmdb/crew.ts"; + import { getLanguagesFromSpokenLanguages } from "@/libs/apis/tmdb/languages"; import { TmdbGenre } from "@/libs/apis/tmdb/schemas/genres.ts"; import { generateDitheredBufferFromUrl } from "@/libs/utils/images.ts"; import { convertToMillions } from "@/libs/utils/numbers.ts"; @@ -11,15 +14,19 @@ import { RuntimeClient } from "@/services/runtime-client.ts"; import { useEntryStore } from "@/stores/entry.ts"; import { canvasFromPixelBuffer } from "@thi.ng/pixel"; - import { Array as Arr, Effect, pipe, String as Str } from "effect"; + import { Array as Arr, Effect, Option, pipe, String as Str } from "effect"; + import { isNotUndefined } from "effect/Predicate"; import { ref, type Ref, type ShallowRef, useTemplateRef, watch } from "vue"; import { useRouter } from "vue-router"; // Types interface AddEntryDisplayData { budget: string; + countries: string[]; genres: TmdbGenreName[]; + hasDiaryEntry: boolean; hasUniqueOriginalTitle: boolean; + languages: string[]; mainCrew: MovieMainCrew; originalLanguage: string; originalTitle: ArtWorkTitle; @@ -55,9 +62,14 @@ // Récupère les données à afficher. displayData.value = { budget: entryStore.tmdbData.budget ? `${String(convertToMillions(entryStore.tmdbData.budget))} M$` : "?", + countries: getCountriesFromCompanies(entryStore.tmdbData.production_companies).pipe( + Option.getOrElse(() => []), + ), genres: Arr.map(entryStore.tmdbData.genres, (genre: TmdbGenre) => genre.name), + hasDiaryEntry: isNotUndefined(entryStore.diaryEntry.artWorkId), hasUniqueOriginalTitle: Str.toLowerCase(entryStore.diaryEntry.originalTitle) !== Str.toLowerCase(entryStore.diaryEntry.title), + languages: getLanguagesFromSpokenLanguages(entryStore.tmdbData.spoken_languages), mainCrew: getMainMovieCrew(entryStore.tmdbData.credits.crew), originalLanguage: entryStore.tmdbData.original_language, originalTitle: entryStore.diaryEntry.originalTitle, @@ -133,17 +145,34 @@ +
+
    + Pays +
  • {{ country }}
  • +
+ +
    + Langues +
  • {{ language }}
  • +
+
+

{{ displayData?.tagline }}

{{ displayData?.overview }}

-
    +
      Genres
    • {{ genre }}

    + + +
    + +
    @@ -198,7 +227,7 @@ text-transform: uppercase; } - .genres { + .inline-list { display: inline-flex; strong { @@ -215,4 +244,8 @@ } } } + + .diary-entry-state { + margin-block-end: var(--s2); + } diff --git a/src/pages/SearchPage.vue b/src/pages/SearchPage.vue index c2408f3..00b9ff1 100644 --- a/src/pages/SearchPage.vue +++ b/src/pages/SearchPage.vue @@ -166,7 +166,7 @@ posterUrl: result.poster_path, releaseDate: DateTime.format(result.release_date, { dateStyle: "short", locale: "sv-SE" }), title: result.title, - tmdbGenres: result.genre_ids, + tmdbGenreIds: result.genre_ids, tmdbId: result.id, } satisfies MergedTmdbDataDiaryEntry, ); diff --git a/src/styles/base/elements.css b/src/styles/base/elements.css index f017eef..0a50be1 100644 --- a/src/styles/base/elements.css +++ b/src/styles/base/elements.css @@ -68,8 +68,3 @@ } } } - -:where(fieldset > legend) { - float: left; - inline-size: 100%; -} diff --git a/src/styles/themes/default/forms.css b/src/styles/themes/default/forms.css index 8f04762..0980873 100644 --- a/src/styles/themes/default/forms.css +++ b/src/styles/themes/default/forms.css @@ -1,11 +1,13 @@ :root { --fields-padding: var(--s-4); --fieldset-legend-spacing: var(--s0); - --input-border: 1px solid var(--root-text-color); - --radio-marker-size: var(--s-2); - --radio-marker-background-color: var(--root-text-color); - --radio-background-color: var(--root-background-color); + --field-background-color: var(--root-background-color); + --field-border: 1px solid var(--root-text-color); + --field-padding: var(--s-2); + --field-text-color: var(--root-text-color); --radio-label-spacing: var(--s-2); + --radio-marker-background-color: var(--root-text-color); + --radio-marker-size: var(--s-2); } /* Groupe de champs. */ @@ -13,13 +15,30 @@ padding: var(--fields-padding); } -input[type="text"], input[type="number"] { - padding: var(--fields-padding); - border: var(--input-border); +/* Ensemble label-champ. */ +.field { + display: flex; + flex-flow: column nowrap; + + &:has(input[type="radio"]) { + flex-flow: row nowrap; + } +} + +/* Champs particuliers. */ +:is(input, select, textarea):not(input[type="radio"]) { + padding: var(--field-padding); + border: var(--field-border); + color: var(--field-text-color); + background-color: var(--field-background-color); &::selection { - color: var(--root-text-color); - background-color: var(--root-background-color); + color: var(--field-background-color); + background-color: var(--field-text-color); + } + + label:has(~ &) { + font-weight: var(--brkly-font-weight-semibold); } } @@ -28,9 +47,9 @@ input[type="radio"] { aspect-ratio: 1/1; inline-size: var(--s-1); block-size: var(--s-1); - border: var(--input-border); + border: var(--field-border); border-radius: 50%; - background: var(--radio-background-color); + background: var(--field-background-color); &::after { content: ""; @@ -45,13 +64,13 @@ input[type="radio"] { background: var(--radio-marker-background-color); } - + label { - padding-left: var(--radio-label-spacing); - } - &:checked { &::after { opacity: 1; } } + + + label { + padding-left: var(--radio-label-spacing); + } }