diff --git a/bun.lock b/bun.lock index f2ed943..95bd96f 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,8 @@ "dependencies": { "@effect/platform": "latest", "@effect/sql-drizzle": "latest", + "@thi.ng/pixel": "latest", + "@thi.ng/pixel-dither": "latest", "a11y-dialog": "latest", "drizzle-orm": "latest", "effect": "latest", @@ -207,13 +209,13 @@ "@dual-bundle/import-meta-resolve": ["@dual-bundle/import-meta-resolve@4.1.0", "", {}, "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg=="], - "@effect/experimental": ["@effect/experimental@0.41.2", "", { "dependencies": { "msgpackr": "^1.10.2", "uuid": "^11.0.3" }, "peerDependencies": { "@effect/platform": "^0.77.2", "@effect/platform-node": "^0.73.2", "effect": "^3.13.2", "ioredis": "^5", "lmdb": "^3", "ws": "^8" }, "optionalPeers": ["@effect/platform-node", "ioredis", "lmdb", "ws"] }, "sha512-8FQmxE7SoZOTOqm6QB9CcdNdTN1dHqaSRlz6pijzvxsq29mWDrHqHfzixessDYVt2QTBshrel+y55Od7pndUCQ=="], + "@effect/experimental": ["@effect/experimental@0.41.4", "", { "dependencies": { "msgpackr": "^1.10.2", "uuid": "^11.0.3" }, "peerDependencies": { "@effect/platform": "^0.77.4", "@effect/platform-node": "^0.73.4", "effect": "^3.13.4", "ioredis": "^5", "lmdb": "^3", "ws": "^8" }, "optionalPeers": ["@effect/platform-node", "ioredis", "lmdb", "ws"] }, "sha512-celrEhl/K2Eis906d3/oOv/3/w+M1jcONvrChG5qQgWYo6CJjSJm4xXopcTbiBhxAhvkd06zABkB3tr/lptUCA=="], - "@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.4", "", { "dependencies": { "find-my-way-ts": "^0.1.5", "multipasta": "^0.2.5" }, "peerDependencies": { "effect": "^3.13.4" } }, "sha512-3jBDn4bAWqRSKARmoMY2NmMxIMM5Py5BqJdUuYJqPyI6jbz7qkOMwgeaF62rWqiqhQLHLTgU4QL/cPwyZl7mVg=="], - "@effect/sql": ["@effect/sql@0.30.2", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.25.1", "uuid": "^11.0.3" }, "peerDependencies": { "@effect/experimental": "^0.41.2", "@effect/platform": "^0.77.2", "effect": "^3.13.2" } }, "sha512-3T8dteCcXKj0jinj9OBfjUnNfqxf8S4lZ74shpRukWjmJUcnGatiy/YW1nV4lewSc0yuKLuly36A93J65AxtuQ=="], + "@effect/sql": ["@effect/sql@0.30.4", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.25.1", "uuid": "^11.0.3" }, "peerDependencies": { "@effect/experimental": "^0.41.4", "@effect/platform": "^0.77.4", "effect": "^3.13.4" } }, "sha512-hyGOZsNRlw09yqBcXCTr1o2+vVIVxEnBMNZzi0ZX5JbS8JBT05O7xAu3OYEzSU6bC5i+uVpJJUgdx2zDlOLkeA=="], - "@effect/sql-drizzle": ["@effect/sql-drizzle@0.29.2", "", { "peerDependencies": { "@effect/sql": "^0.30.2", "drizzle-orm": "^0.31", "effect": "^3.13.2" } }, "sha512-dYxDL3954I8o+yaSzSvsmmZYlpyZgmWoy9PC8y5BpHFx/+TIEPdw5ZlSAwjDafPH3GTWo2EsSQWzVTDFC+Un2A=="], + "@effect/sql-drizzle": ["@effect/sql-drizzle@0.29.4", "", { "peerDependencies": { "@effect/sql": "^0.30.4", "drizzle-orm": "^0.31", "effect": "^3.13.4" } }, "sha512-Hz8RypUu5g/V3DVmD0WLK+Nqy9H/V/GA2ew41sSZhJ0fTmxaCoQ08it23qypeNN66CCJNF5uE9OWnHl10cfKGA=="], "@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=="], @@ -365,6 +367,22 @@ "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], + "@thi.ng/api": ["@thi.ng/api@8.11.21", "", {}, "sha512-J6BUdUtFtwZirL3M9tkCiqBXj228z7zkxWOaDWTymwBeqY9s02vJP3mQV8l5p+YPDIRmYx/q7XVuLW1UTJRN/A=="], + + "@thi.ng/canvas": ["@thi.ng/canvas@1.0.8", "", {}, "sha512-r4bRWAsiaaNx+ihTtQDi1RQFMfOLwGgoSbZhdxLzEo6t1Ga5a/cqv/WKqUWLjD1LHjxhtflS8uPcihD2ETyAOg=="], + + "@thi.ng/checks": ["@thi.ng/checks@3.7.1", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-RfVBQgJN0kr00SKptAAzdDOaaRtWlctqegYogynTLkUhf8Ck516Efk/macgWTzSLEPgcumN7E9F1F3lgfRCWew=="], + + "@thi.ng/errors": ["@thi.ng/errors@2.5.27", "", {}, "sha512-t1sgGuZqHv81lzNPSRySGHnDBvtt6h3MIMn3LdZnqMR0swwOIApw6YlheMYB63u94NdtuneQYcjdvbhOsHbwPQ=="], + + "@thi.ng/math": ["@thi.ng/math@5.11.21", "", { "dependencies": { "@thi.ng/api": "^8.11.21" } }, "sha512-JLjHdQbCpIP6F76Vq8yBtRtDOaUJ5HKsyEhU++8bjPX7VeDf8um4Ba/PUQZS+SpX0ghTZrqirqoI7H6wWz/TaQ=="], + + "@thi.ng/pixel": ["@thi.ng/pixel@7.3.19", "", { "dependencies": { "@thi.ng/api": "^8.11.21", "@thi.ng/canvas": "^1.0.8", "@thi.ng/checks": "^3.7.1", "@thi.ng/errors": "^2.5.27", "@thi.ng/math": "^5.11.21", "@thi.ng/porter-duff": "^2.1.99" } }, "sha512-k1oUFPktxOcJEh0RuzgwoZGBkNqB1zMNvk2QILph54Cj1JJH3CcAuqJTu+N6QkXoxsgoM4DtMiDcmIdyrRokJQ=="], + + "@thi.ng/pixel-dither": ["@thi.ng/pixel-dither@1.1.159", "", { "dependencies": { "@thi.ng/checks": "^3.7.1", "@thi.ng/math": "^5.11.21", "@thi.ng/pixel": "^7.3.19" } }, "sha512-1tQfZUPgTEe/sn0URTHbkDEtWpJyqC4WqR9BMdOcE+g+pHhp1AjGB+eru1Mhx0WKJ/jcYl669U73Qooh8L2V6A=="], + + "@thi.ng/porter-duff": ["@thi.ng/porter-duff@2.1.99", "", { "dependencies": { "@thi.ng/api": "^8.11.21" } }, "sha512-HC4rqfHGfAMijUoNlZslRZypb7MJ8BO6XpRF2Ol/O6JqHzhHtWlwbB/WGfoSiAUfdEHprSZ3KsPCDEl7MnRdpg=="], + "@types/bun": ["@types/bun@1.2.4", "", { "dependencies": { "bun-types": "1.2.4" } }, "sha512-QtuV5OMR8/rdKJs213iwXDpfVvnskPXY/S0ZiFbsTjQZycuqPbMW8Gf/XhLfwE5njW8sxI2WjISURXPlHypMFA=="], "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], @@ -483,7 +501,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@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], @@ -561,9 +579,9 @@ "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.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-/w+CPqHDJ33Wq7xC4YKAchrEEPtjvxh563xH9kDTZp99seNYBoBs87vl8DJwartEjj+KLQLP8PzoDne+XmGT2A=="], + "effect": ["effect@3.13.4", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-XZgCImyBpONuKdsBRk37JfV7242yxTu8r/TcL5ZELIyqRbMYa+Prr86cz1INxXi7iFXfU0havZkCJGyYp1BsiA=="], - "electron-to-chromium": ["electron-to-chromium@1.5.104", "", {}, "sha512-Us9M2L4cO/zMBqVkJtnj353nQhMju9slHm62NprKTmdF3HH8wYOtNvDFq/JB2+ZRoGLzdvYDiATlMHs98XBM1g=="], + "electron-to-chromium": ["electron-to-chromium@1.5.109", "", {}, "sha512-AidaH9JETVRr9DIPGfp1kAarm/W6hRJTPuCnkF+2MqhF4KaAgRIcBc8nvjk+YMXZhwfISof/7WG29eS4iGxQLQ=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -623,7 +641,7 @@ "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="], - "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=="], "fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="], @@ -885,7 +903,7 @@ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], - "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], @@ -927,7 +945,7 @@ "strip-json-comments": ["strip-json-comments@5.0.1", "", {}, "sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw=="], - "stylelint": ["stylelint@16.14.1", "", { "dependencies": { "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "@csstools/media-query-list-parser": "^4.0.2", "@csstools/selector-specificity": "^5.0.0", "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", "css-tree": "^3.1.0", "debug": "^4.3.7", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^10.0.5", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", "ignore": "^7.0.3", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "known-css-properties": "^0.35.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.5.1", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", "supports-hyperlinks": "^3.1.0", "svg-tags": "^1.0.0", "table": "^6.9.0", "write-file-atomic": "^5.0.1" }, "bin": { "stylelint": "bin/stylelint.mjs" } }, "sha512-oqCL7AC3786oTax35T/nuLL8p2C3k/8rHKAooezrPGRvUX0wX+qqs5kMWh5YYT4PHQgVDobHT4tw55WgpYG6Sw=="], + "stylelint": ["stylelint@16.15.0", "", { "dependencies": { "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "@csstools/media-query-list-parser": "^4.0.2", "@csstools/selector-specificity": "^5.0.0", "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", "css-tree": "^3.1.0", "debug": "^4.3.7", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^10.0.6", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", "ignore": "^7.0.3", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "known-css-properties": "^0.35.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.5.3", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.1.0", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", "supports-hyperlinks": "^3.2.0", "svg-tags": "^1.0.0", "table": "^6.9.0", "write-file-atomic": "^5.0.1" }, "bin": { "stylelint": "bin/stylelint.mjs" } }, "sha512-OK6Rs7EPdcdmjqiDycadZY4fw3f5/TC1X6/tGjnF3OosbwCeNs7nG+79MCAtjEg7ckwqTJTsku08e0Rmaz5nUw=="], "stylelint-config-clean-order": ["stylelint-config-clean-order@7.0.0", "", { "dependencies": { "stylelint-order": "^6.0.4" }, "peerDependencies": { "stylelint": ">=14" } }, "sha512-R28w1xNliIbem3o+VIrNjAU8cMgxrGlDoXVqWW7lJ1OvSDsmNGj5aKSW6Xm7i5PK4E99T3Hs19BJFni5IbE56g=="], @@ -969,13 +987,13 @@ "type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], - "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=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "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/cfg/dprint.json b/cfg/dprint.json index 1d81251..0e07718 100644 --- a/cfg/dprint.json +++ b/cfg/dprint.json @@ -66,12 +66,12 @@ }, "newLineKind": "lf", "plugins": [ - "https://plugins.dprint.dev/typescript-0.93.4.wasm", - "https://plugins.dprint.dev/json-0.19.4.wasm", - "https://plugins.dprint.dev/markdown-0.17.8.wasm", - "https://plugins.dprint.dev/toml-0.6.4.wasm", + "https://plugins.dprint.dev/typescript-0.94.0.wasm", + "https://plugins.dprint.dev/json-0.20.0.wasm", + "https://plugins.dprint.dev/markdown-0.18.0.wasm", + "https://plugins.dprint.dev/toml-0.7.0.wasm", "https://plugins.dprint.dev/g-plane/malva-v0.11.1.wasm", - "https://plugins.dprint.dev/g-plane/markup_fmt-v0.18.0.wasm", + "https://plugins.dprint.dev/g-plane/markup_fmt-v0.19.0.wasm", "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm", "https://plugins.dprint.dev/exec-0.5.1.json@492414e39dea4dccc07b4af796d2f4efdb89e84bae2bd4e1e924c0cc050855bf" ], diff --git a/cfg/eslint.config.mts b/cfg/eslint.config.mts deleted file mode 100644 index fffcb7c..0000000 --- a/cfg/eslint.config.mts +++ /dev/null @@ -1,75 +0,0 @@ -import { defineConfigWithVueTs, vueTsConfigs } from "@vue/eslint-config-typescript"; -import perfectionist from "eslint-plugin-perfectionist"; -import vue from "eslint-plugin-vue"; -import globals from "globals"; - -export default defineConfigWithVueTs( - { - files: ["**/*.{js,mjs,ts,mts,vue}"], - languageOptions: { ecmaVersion: "latest", globals: { ...globals.browser, ...globals.es2025 } }, - name: "app/files-to-lint", - }, - { ignores: [".cache/", "dist/", "node_modules/"], name: "app/files-to-ignore" }, - vueTsConfigs.strictTypeChecked, - vueTsConfigs.stylisticTypeChecked, - vue.configs["flat/recommended"], - { - name: "app/no-vue-formatting", - rules: { - "vue/array-bracket-newline": "off", - "vue/array-bracket-spacing": "off", - "vue/array-element-newline": "off", - "vue/arrow-spacing": "off", - "vue/attributes-order": ["error", { alphabetical: true }], - "vue/block-spacing": "off", - "vue/block-tag-newline": "off", - "vue/brace-style": "off", - "vue/comma-dangle": "off", - "vue/comma-spacing": "off", - "vue/comma-style": "off", - "vue/dot-location": "off", - "vue/first-attribute-linebreak": "off", - "vue/func-call-spacing": "off", - "vue/html-closing-bracket-newline": "off", - "vue/html-closing-bracket-spacing": "off", - "vue/html-comment-content-newline": "off", - "vue/html-comment-content-spacing": "off", - "vue/html-comment-indent": "off", - "vue/html-indent": "off", - "vue/html-quotes": "off", - "vue/html-self-closing": "off", - "vue/key-spacing": "off", - "vue/keyword-spacing": "off", - "vue/max-attributes-per-line": "off", - "vue/max-len": "off", - "vue/multiline-html-element-content-newline": "off", - "vue/multiline-ternary": "off", - "vue/new-line-between-multi-line-property": "off", - "vue/no-extra-parens": "off", - "vue/no-multi-spaces": "off", - "vue/no-spaces-around-equal-signs-in-attribute": "off", - "vue/object-curly-newline": "off", - "vue/object-curly-spacing": "off", - "vue/object-property-newline": "off", - "vue/operator-linebreak": "off", - "vue/padding-line-between-blocks": "off", - "vue/padding-line-between-tags": "off", - "vue/padding-lines-in-component-definition": "off", - "vue/quote-props": "off", - "vue/script-indent": "off", - "vue/singleline-html-element-content-newline": "off", - "vue/space-in-parens": "off", - "vue/space-infix-ops": "off", - "vue/space-unary-ops": "off", - "vue/template-curly-spacing": "off", - "vue/v-for-delimiter-style": "off", - }, - }, - { - name: "ts/no-annoying-rules", - rules: { - "@typescript-eslint/no-misused-spread": "off", - }, - }, - perfectionist.configs["recommended-natural"], -); diff --git a/cspell.json b/cspell.json index 0c66d33..4945c2c 100644 --- a/cspell.json +++ b/cspell.json @@ -12,6 +12,7 @@ "AUTOINCREMENT", "vtsls", "quartary", - "fieldset" + "fieldset", + "tabindex" ] } diff --git a/justfile b/justfile index 3d0d4b7..71d34e8 100755 --- a/justfile +++ b/justfile @@ -2,8 +2,8 @@ set shell := ["fish", "-c"] # Variables de chemins de configuration. -drizzleConfigFile := "src/db/drizzle.config.ts" -esLintConfigFile := "cfg/eslint.config.mts" +drizzleConfigFile := "cfg/drizzle.config.ts" +esLintConfigFile := "eslint.config.mts" esLintCssConfigFile := "cfg/eslint-css.config.mts" knipConfigFile := "cfg/knip.config.ts" prettierConfigFile := "cfg/prettier.config.mjs" diff --git a/package.json b/package.json index 3f8b915..9cfb458 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,13 @@ "type": "module", "private": true, "dependencies": { - "@effect/platform": "^0.77.2", - "@effect/sql-drizzle": "^0.29.2", + "@effect/platform": "^0.77.4", + "@effect/sql-drizzle": "^0.29.4", + "@thi.ng/pixel": "^7.3.19", + "@thi.ng/pixel-dither": "^1.1.159", "a11y-dialog": "^8.1.1", "drizzle-orm": "^0.40.0", - "effect": "^3.13.2", + "effect": "^3.13.4", "pinia": "^3.0.1", "sqlocal": "^0.14.0", "vue": "^3.5.13", @@ -34,13 +36,13 @@ "prettier": "^3.5.2", "prettier-plugin-pkg": "^0.18.1", "prettier-plugin-sh": "^0.15.0", - "stylelint": "^16.14.1", + "stylelint": "^16.15.0", "stylelint-config-clean-order": "^7.0.0", "stylelint-config-standard": "^37.0.0", "stylelint-declaration-block-no-ignored-properties": "^2.8.0", "stylelint-plugin-logical-css": "^1.2.1", "tsr": "^1.3.4", - "typescript": "^5.7.3", + "typescript": "^5.8.2", "vite": "^6.2.0", "vue-tsc": "^2.2.4" } diff --git a/src/components/EntryEditDialog.vue b/src/components/EntryEditDialog.vue new file mode 100644 index 0000000..83f246c --- /dev/null +++ b/src/components/EntryEditDialog.vue @@ -0,0 +1,10 @@ + + + diff --git a/src/components/SearchMediaDialog.vue b/src/components/SearchMediaDialog.vue index d64d3c8..44ec129 100644 --- a/src/components/SearchMediaDialog.vue +++ b/src/components/SearchMediaDialog.vue @@ -1,4 +1,5 @@ - / - + / + Nom Année + Popularité - {{ result.original_title }} + {{ result[1].original_title }} - {{ result.release_date }} + {{ result[1].release_date }} + {{ result[1].popularity }} @@ -44,7 +73,7 @@ } thead { - border-block-end: 1px solid var(--color-primary); + border-block-end: 1px solid var(--root-text-color); tr > * + * { padding-inline-start: var(--s-2); @@ -71,13 +100,13 @@ cursor: pointer; &:hover { - background: var(--color-primary); - color: var(--color-secondary); + background: var(--root-text-color); + color: var(--root-background-color); } &:active { - outline: 1px solid var(--color-secondary); - outline-offset: -0.1rem; + outline: 2px solid var(--root-background-color); + outline-offset: -0.3rem; } } diff --git a/src/db/drizzle/0000_perfect_justice.sql b/src/db/drizzle/0000_open_the_twelve.sql similarity index 73% rename from src/db/drizzle/0000_perfect_justice.sql rename to src/db/drizzle/0000_open_the_twelve.sql index 62bb55a..37a027b 100644 --- a/src/db/drizzle/0000_perfect_justice.sql +++ b/src/db/drizzle/0000_open_the_twelve.sql @@ -1,25 +1,15 @@ -CREATE TABLE `art_works` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `medium_type_id` integer, - `name` text NOT NULL, - `release_date` text(10) NOT NULL, - FOREIGN KEY (`medium_type_id`) REFERENCES `media_types`(`id`) ON UPDATE no action ON DELETE no action -); ---> statement-breakpoint CREATE TABLE `diary_entries` ( - `art_work_id` integer, + `art_work_id` integer NOT NULL, `date_created` text(10) NOT NULL, `date_modified` text(10) NOT NULL, `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `state_id` integer, - `user_id` integer, + `state_id` integer NOT NULL, FOREIGN KEY (`art_work_id`) REFERENCES `art_works`(`id`) ON UPDATE no action ON DELETE no action, - FOREIGN KEY (`state_id`) REFERENCES `diary_entries_states`(`id`) ON UPDATE no action ON DELETE no action, - FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action + FOREIGN KEY (`state_id`) REFERENCES `diary_entries_states`(`id`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint CREATE TABLE `diary_entries_genres` ( - `art_work_id` integer, + `art_work_id` integer NOT NULL, `genre_id` integer, `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, FOREIGN KEY (`art_work_id`) REFERENCES `art_works`(`id`) ON UPDATE no action ON DELETE no action, @@ -32,6 +22,25 @@ CREATE TABLE `diary_entries_states` ( ); --> statement-breakpoint CREATE UNIQUE INDEX `diary_entries_states_state_unique` ON `diary_entries_states` (`state`);--> statement-breakpoint +CREATE TABLE `viewings` ( + `art_work_id` integer NOT NULL, + `date` text(10) NOT NULL, + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + FOREIGN KEY (`art_work_id`) REFERENCES `art_works`(`id`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE TABLE `art_works` ( + `cover_path` text, + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `medium_type_id` integer NOT NULL, + `name` text NOT NULL, + `release_date` text(10) NOT NULL, + `tmdb_id` integer NOT NULL, + FOREIGN KEY (`medium_type_id`) REFERENCES `media_types`(`id`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE UNIQUE INDEX `art_works_cover_path_unique` ON `art_works` (`cover_path`);--> statement-breakpoint +CREATE UNIQUE INDEX `art_works_tmdb_id_unique` ON `art_works` (`tmdb_id`);--> statement-breakpoint CREATE TABLE `genres` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `name` text NOT NULL, @@ -47,20 +56,4 @@ CREATE TABLE `media_types` ( ); --> statement-breakpoint CREATE UNIQUE INDEX `media_types_name_unique` ON `media_types` (`name`);--> statement-breakpoint -CREATE UNIQUE INDEX `media_types_slug_unique` ON `media_types` (`slug`);--> statement-breakpoint -CREATE TABLE `users` ( - `email` text NOT NULL, - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `name` text NOT NULL -); ---> statement-breakpoint -CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);--> statement-breakpoint -CREATE UNIQUE INDEX `users_name_unique` ON `users` (`name`);--> statement-breakpoint -CREATE TABLE `viewings` ( - `art_work_id` integer, - `date` text(10) NOT NULL, - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `user_id` integer, - FOREIGN KEY (`art_work_id`) REFERENCES `art_works`(`id`) ON UPDATE no action ON DELETE no action, - FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action -); +CREATE UNIQUE INDEX `media_types_slug_unique` ON `media_types` (`slug`); \ No newline at end of file diff --git a/src/db/drizzle/meta/0000_snapshot.json b/src/db/drizzle/meta/0000_snapshot.json index 9ae39c9..b0681c4 100644 --- a/src/db/drizzle/meta/0000_snapshot.json +++ b/src/db/drizzle/meta/0000_snapshot.json @@ -1,45 +1,9 @@ { "version": "6", "dialect": "sqlite", - "id": "7f64c80e-6fd1-4f8c-859c-dac137206238", + "id": "da9e1cf6-aba7-4b5a-a839-3b0fe3dce876", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { - "art_works": { - "name": "art_works", - "columns": { - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true }, - "medium_type_id": { - "name": "medium_type_id", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false }, - "release_date": { - "name": "release_date", - "type": "text(10)", - "primaryKey": false, - "notNull": true, - "autoincrement": false - } - }, - "indexes": {}, - "foreignKeys": { - "art_works_medium_type_id_media_types_id_fk": { - "name": "art_works_medium_type_id_media_types_id_fk", - "tableFrom": "art_works", - "tableTo": "media_types", - "columnsFrom": ["medium_type_id"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, "diary_entries": { "name": "diary_entries", "columns": { @@ -47,7 +11,7 @@ "name": "art_work_id", "type": "integer", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false }, "date_created": { @@ -64,19 +28,18 @@ "notNull": true, "autoincrement": false }, - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true }, + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, "state_id": { "name": "state_id", "type": "integer", "primaryKey": false, - "notNull": false, - "autoincrement": false - }, - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false } }, @@ -86,8 +49,12 @@ "name": "diary_entries_art_work_id_art_works_id_fk", "tableFrom": "diary_entries", "tableTo": "art_works", - "columnsFrom": ["art_work_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "art_work_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" }, @@ -95,17 +62,12 @@ "name": "diary_entries_state_id_diary_entries_states_id_fk", "tableFrom": "diary_entries", "tableTo": "diary_entries_states", - "columnsFrom": ["state_id"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - }, - "diary_entries_user_id_users_id_fk": { - "name": "diary_entries_user_id_users_id_fk", - "tableFrom": "diary_entries", - "tableTo": "users", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "state_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" } @@ -121,7 +83,7 @@ "name": "art_work_id", "type": "integer", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false }, "genre_id": { @@ -131,7 +93,13 @@ "notNull": false, "autoincrement": false }, - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true } + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + } }, "indexes": {}, "foreignKeys": { @@ -139,8 +107,12 @@ "name": "diary_entries_genres_art_work_id_art_works_id_fk", "tableFrom": "diary_entries_genres", "tableTo": "art_works", - "columnsFrom": ["art_work_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "art_work_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" }, @@ -148,8 +120,12 @@ "name": "diary_entries_genres_genre_id_genres_id_fk", "tableFrom": "diary_entries_genres", "tableTo": "genres", - "columnsFrom": ["genre_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "genre_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" } @@ -161,13 +137,27 @@ "diary_entries_states": { "name": "diary_entries_states", "columns": { - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true }, - "state": { "name": "state", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false } + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } }, "indexes": { "diary_entries_states_state_unique": { "name": "diary_entries_states_state_unique", - "columns": ["state"], + "columns": [ + "state" + ], "isUnique": true } }, @@ -176,54 +166,6 @@ "uniqueConstraints": {}, "checkConstraints": {} }, - "genres": { - "name": "genres", - "columns": { - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true }, - "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false }, - "slug": { "name": "slug", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false } - }, - "indexes": { - "genres_name_unique": { "name": "genres_name_unique", "columns": ["name"], "isUnique": true }, - "genres_slug_unique": { "name": "genres_slug_unique", "columns": ["slug"], "isUnique": true } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "media_types": { - "name": "media_types", - "columns": { - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true }, - "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false }, - "slug": { "name": "slug", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false } - }, - "indexes": { - "media_types_name_unique": { "name": "media_types_name_unique", "columns": ["name"], "isUnique": true }, - "media_types_slug_unique": { "name": "media_types_slug_unique", "columns": ["slug"], "isUnique": true } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, - "users": { - "name": "users", - "columns": { - "email": { "name": "email", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false }, - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true }, - "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true, "autoincrement": false } - }, - "indexes": { - "users_email_unique": { "name": "users_email_unique", "columns": ["email"], "isUnique": true }, - "users_name_unique": { "name": "users_name_unique", "columns": ["name"], "isUnique": true } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, "viewings": { "name": "viewings", "columns": { @@ -231,17 +173,22 @@ "name": "art_work_id", "type": "integer", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false }, - "date": { "name": "date", "type": "text(10)", "primaryKey": false, "notNull": true, "autoincrement": false }, - "id": { "name": "id", "type": "integer", "primaryKey": true, "notNull": true, "autoincrement": true }, - "user_id": { - "name": "user_id", - "type": "integer", + "date": { + "name": "date", + "type": "text(10)", "primaryKey": false, - "notNull": false, + "notNull": true, "autoincrement": false + }, + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true } }, "indexes": {}, @@ -250,17 +197,12 @@ "name": "viewings_art_work_id_art_works_id_fk", "tableFrom": "viewings", "tableTo": "art_works", - "columnsFrom": ["art_work_id"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - }, - "viewings_user_id_users_id_fk": { - "name": "viewings_user_id_users_id_fk", - "tableFrom": "viewings", - "tableTo": "users", - "columnsFrom": ["user_id"], - "columnsTo": ["id"], + "columnsFrom": [ + "art_work_id" + ], + "columnsTo": [ + "id" + ], "onDelete": "no action", "onUpdate": "no action" } @@ -268,10 +210,189 @@ "compositePrimaryKeys": {}, "uniqueConstraints": {}, "checkConstraints": {} + }, + "art_works": { + "name": "art_works", + "columns": { + "cover_path": { + "name": "cover_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "medium_type_id": { + "name": "medium_type_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "release_date": { + "name": "release_date", + "type": "text(10)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tmdb_id": { + "name": "tmdb_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "art_works_cover_path_unique": { + "name": "art_works_cover_path_unique", + "columns": [ + "cover_path" + ], + "isUnique": true + }, + "art_works_tmdb_id_unique": { + "name": "art_works_tmdb_id_unique", + "columns": [ + "tmdb_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "art_works_medium_type_id_media_types_id_fk": { + "name": "art_works_medium_type_id_media_types_id_fk", + "tableFrom": "art_works", + "tableTo": "media_types", + "columnsFrom": [ + "medium_type_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "genres": { + "name": "genres", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "genres_name_unique": { + "name": "genres_name_unique", + "columns": [ + "name" + ], + "isUnique": true + }, + "genres_slug_unique": { + "name": "genres_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "media_types": { + "name": "media_types", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "media_types_name_unique": { + "name": "media_types_name_unique", + "columns": [ + "name" + ], + "isUnique": true + }, + "media_types_slug_unique": { + "name": "media_types_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} } }, "views": {}, "enums": {}, - "_meta": { "schemas": {}, "tables": {}, "columns": {} }, - "internal": { "indexes": {} } + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } } diff --git a/src/db/drizzle/meta/_journal.json b/src/db/drizzle/meta/_journal.json index d1efd91..fde85a2 100644 --- a/src/db/drizzle/meta/_journal.json +++ b/src/db/drizzle/meta/_journal.json @@ -1,5 +1,13 @@ { "version": "7", "dialect": "sqlite", - "entries": [{ "idx": 0, "version": "6", "when": 1739953332871, "tag": "0000_perfect_justice", "breakpoints": true }] + "entries": [ + { + "idx": 0, + "version": "6", + "when": 1740666437095, + "tag": "0000_open_the_twelve", + "breakpoints": true + } + ] } diff --git a/src/db/schemas/works.ts b/src/db/schemas/works.ts index 9b82def..ea04fac 100644 --- a/src/db/schemas/works.ts +++ b/src/db/schemas/works.ts @@ -16,10 +16,12 @@ export const MediaTypes = table("media_types", { }); export const ArtWorks = table("art_works", { + coverPath: t.text("cover_path").unique(), id: t.integer("id").primaryKey({ autoIncrement: true }), mediumTypeId: t.integer("medium_type_id").references((): AnySQLiteColumn => MediaTypes.id).notNull(), name: t.text("name").notNull(), releaseDate: t.text("release_date", { length: 10 }).notNull(), + tmdbId: t.integer("tmdb_id").notNull().unique(), }); export const Genres = table("genres", { @@ -31,17 +33,28 @@ export const Genres = table("genres", { // Schémas export const MediaTypeSchema = Schema.Struct({ + /** L'ID numérique du type de média. */ id: Schema.NonNegativeInt, + /** Le nom du type de média. */ name: Schema.NonEmptyString, + /** L'ID alphabétique du type de média. */ slug: Schema.Enums(MEDIA_TYPES), }); export type MediaType = Schema.Schema.Type; export const ArtWorkSchema = Schema.Struct({ + /** Le chemin de l'image de la pochette de l'oeuvre d'art. */ + coverPath: Schema.Union(Schema.String, Schema.Null), + /** L'ID numérique de l'ouvre d'art. */ id: Schema.NonNegativeInt, + /** L'ID numérique du type de l'oeuvre d'art. */ mediumTypeId: Schema.NonNegativeInt, + /** Le nom de l'oeuvre d'art. */ name: Schema.NonEmptyString, + /** La date de sortie de l'oeuvre d'art au format YYYY-MM-DD. */ releaseDate: Schema.String, + /** L'ID numérique de l'oeuvre sur la base de données TMDB. */ + tmdbId: Schema.NonNegativeInt, }); export type ArtWork = Schema.Schema.Type; diff --git a/src/libs/apis/tmdb/orders.ts b/src/libs/apis/tmdb/orders.ts new file mode 100644 index 0000000..a31139e --- /dev/null +++ b/src/libs/apis/tmdb/orders.ts @@ -0,0 +1,22 @@ +import type { MergedTmdbLocalData } from "@/libs/search/schemas"; + +import { Order } from "effect"; + +import type { TmdbMovieSearchResponseResult } from "./schemas"; + +export const byTitle = Order.mapInput( + Order.string, + (tmdbEntry: TmdbMovieSearchResponseResult) => tmdbEntry.original_title, +); + +export const byReleaseDate = Order.mapInput( + Order.string, + (tmdbEntry: TmdbMovieSearchResponseResult) => tmdbEntry.release_date, +); + +// Tuples + +export const tupleByTitle = Order.mapInput( + Order.string, + (data: [number, MergedTmdbLocalData]) => data[1].title, +); diff --git a/src/libs/apis/tmdb/schemas.ts b/src/libs/apis/tmdb/schemas.ts index c9d1ea8..e3653ff 100644 --- a/src/libs/apis/tmdb/schemas.ts +++ b/src/libs/apis/tmdb/schemas.ts @@ -25,8 +25,9 @@ export class TmdbMovieSearchQueryParams extends Schema.Class("TmdbMovieSearchResponseResults")({ + +export class TmdbMovieSearchResponseResult + extends Schema.Class("TmdbMovieSearchResponseResult")({ adult: Schema.Boolean, backdrop_path: Schema.Union(Schema.String, Schema.Null), genre_ids: Schema.Array(Schema.NonNegativeInt), @@ -46,7 +47,7 @@ export class TmdbMovieSearchResponseResults export class TmdbMovieSearchResponse extends Schema.Class("TmdbMovieSearchResponse")({ page: Schema.NonNegativeInt, - results: Schema.Array(TmdbMovieSearchResponseResults), + results: Schema.Array(TmdbMovieSearchResponseResult), total_pages: Schema.NonNegativeInt, total_results: Schema.NonNegativeInt, }) {} diff --git a/src/libs/search/schemas.ts b/src/libs/search/schemas.ts index 5f582de..19f6d7e 100644 --- a/src/libs/search/schemas.ts +++ b/src/libs/search/schemas.ts @@ -6,3 +6,21 @@ export class SearchPageQueryParams extends Schema.Class(" type: Schema.Enums(MEDIA_TYPES), year: Schema.String, }) {} + +export class MergedTmdbLocalData extends Schema.Class("MergedTmdbLocalData")({ + artWorkCoverPath: Schema.Union(Schema.String, Schema.Null), + artWorkId: Schema.NonNegativeInt.pipe(Schema.optional), + artWorkMediumTypeId: Schema.NonNegativeInt.pipe(Schema.optional), + entryDateCreated: Schema.String.pipe(Schema.optional), + entryDateModified: Schema.String.pipe(Schema.optional), + entryId: Schema.NonNegativeInt.pipe(Schema.optional), + entryStateId: Schema.NonNegativeInt.pipe(Schema.optional), + genre_ids: Schema.Array(Schema.NonNegativeInt), + original_language: Schema.String, + original_title: Schema.String, + overview: Schema.String, + popularity: Schema.Number, + release_date: Schema.String, + title: Schema.String, + tmdbId: Schema.NonNegativeInt, +}) {} diff --git a/src/libs/search/types.d.ts b/src/libs/search/types.d.ts new file mode 100644 index 0000000..579e427 --- /dev/null +++ b/src/libs/search/types.d.ts @@ -0,0 +1,10 @@ +import type { ArtWork, DiaryEntry } from "@/db/schemas"; + +import type { TmdbMovieSearchResponseResult } from "../apis/tmdb/schemas"; + +/** Page de réponse de l'API TMDB avec les données locales correspondantes. */ +export interface TmdbDataWithLocalData { + artWork?: ArtWork; + entry?: DiaryEntry; + tmdbData: TmdbMovieSearchResponseResult; +} diff --git a/src/libs/utils/effects.ts b/src/libs/utils/effects.ts index 3c7f181..55e9fa7 100644 --- a/src/libs/utils/effects.ts +++ b/src/libs/utils/effects.ts @@ -13,3 +13,5 @@ export const singleResultOrFail = (orFail: () => E) => Effect.mapError(_ => orFail()), ) ); + +export const getOrUndefined = (a: Effect.Effect) => Effect.orElseSucceed(a, () => undefined); diff --git a/src/pages/SearchPage.vue b/src/pages/SearchPage.vue index ca450cb..0790774 100644 --- a/src/pages/SearchPage.vue +++ b/src/pages/SearchPage.vue @@ -1,7 +1,6 @@
/