diff --git a/package.json b/package.json index 88d45e67d..1c8c4b54c 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,6 @@ "overrides": { "es-abstract": "~1.23.9", "m3u8-parser>@babel/runtime": "-" - }, - "patchedDependencies": { - "shaka-player": "patches/shaka-player.patch" } }, "wireit": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 576486ce7..e27b83a0c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,11 +8,6 @@ overrides: es-abstract: ~1.23.9 m3u8-parser>@babel/runtime: '-' -patchedDependencies: - shaka-player: - hash: ztcamgtqc3a62la4l6p3d6w4ae - path: patches/shaka-player.patch - importers: .: @@ -39,9 +34,6 @@ importers: '@epic-web/restore-scroll': specifier: 1.1.1 version: 1.1.1(react-router-dom@7.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0) - '@ffmpeg/ffmpeg': - specifier: 0.12.15 - version: 0.12.15 '@headlessui/react': specifier: 2.2.0 version: 2.2.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -69,27 +61,15 @@ importers: immer: specifier: 10.1.1 version: 10.1.1 - lodash: - specifier: 4.17.21 - version: 4.17.21 - luxon: - specifier: 3.5.0 - version: 3.5.0 m3u8-parser: specifier: 7.2.0 version: 7.2.0 - p-min-delay: - specifier: 4.0.2 - version: 4.0.2 react: specifier: 19.0.0 version: 19.0.0 react-dom: specifier: 19.0.0 version: 19.0.0(react@19.0.0) - react-ellipsis-component: - specifier: 1.1.11 - version: 1.1.11(react@19.0.0) react-final-form: specifier: 6.5.9 version: 6.5.9(final-form@4.20.10)(react@19.0.0) @@ -123,12 +103,6 @@ importers: valibot: specifier: 1.0.0-rc.3 version: 1.0.0-rc.3(typescript@5.7.2) - view-transitions-polyfill: - specifier: 1.0.3 - version: 1.0.3 - zod: - specifier: 3.24.1 - version: 3.24.1 zustand: specifier: 5.0.3 version: 5.0.3(@types/react@19.0.1)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.4.0(react@19.0.0)) @@ -148,12 +122,6 @@ importers: '@babel/preset-typescript': specifier: 7.26.0 version: 7.26.0(@babel/core@7.26.0) - '@ffmpeg/core': - specifier: 0.12.10 - version: 0.12.10 - '@ffmpeg/util': - specifier: 0.12.2 - version: 0.12.2 '@iconify/json': specifier: 2.2.317 version: 2.2.317 @@ -178,18 +146,15 @@ importers: '@types/wicg-task-scheduling': specifier: 2024.1.0 version: 2024.1.0 - '@unocss/preset-icons': - specifier: 66.1.0-beta.5 - version: 66.1.0-beta.5 '@unocss/preset-wind3': - specifier: 66.1.0-beta.5 - version: 66.1.0-beta.5 + specifier: 66.1.0-beta.10 + version: 66.1.0-beta.10 '@unocss/reset': - specifier: 66.1.0-beta.5 - version: 66.1.0-beta.5 - '@unocss/runtime': - specifier: 66.1.0-beta.5 - version: 66.1.0-beta.5 + specifier: 66.1.0-beta.10 + version: 66.1.0-beta.10 + '@unocss/webpack': + specifier: 66.1.0-beta.10 + version: 66.1.0-beta.10(webpack@5.96.1) '@wsh-2025/configs': specifier: workspace:* version: link:../configs @@ -199,21 +164,27 @@ importers: babel-loader: specifier: 9.2.1 version: 9.2.1(@babel/core@7.26.0)(webpack@5.96.1) - core-js: - specifier: 3.41.0 - version: 3.41.0 + css-loader: + specifier: 7.1.2 + version: 7.1.2(webpack@5.96.1) + dayjs: + specifier: 1.11.13 + version: 1.11.13 hls.js: specifier: 1.5.17 version: 1.5.17 - shaka-player: - specifier: 4.12.5 - version: 4.12.5(patch_hash=ztcamgtqc3a62la4l6p3d6w4ae) + mini-css-extract-plugin: + specifier: 2.9.2 + version: 2.9.2(webpack@5.96.1) + style-loader: + specifier: 4.0.0 + version: 4.0.0(webpack@5.96.1) typescript: specifier: 5.7.2 version: 5.7.2 - video.js: - specifier: 8.21.0 - version: 8.21.0 + unocss: + specifier: 66.1.0-beta.10 + version: 66.1.0-beta.10(@unocss/webpack@66.1.0-beta.10(webpack@5.96.1)) webpack: specifier: 5.96.1 version: 5.96.1(webpack-cli@5.1.4) @@ -240,22 +211,22 @@ importers: version: 2.0.5 eslint: specifier: 9.15.0 - version: 9.15.0 + version: 9.15.0(jiti@2.4.2) eslint-config-prettier: specifier: 9.1.0 - version: 9.1.0(eslint@9.15.0) + version: 9.1.0(eslint@9.15.0(jiti@2.4.2)) eslint-import-resolver-typescript: specifier: 3.6.3 - version: 3.6.3(eslint-plugin-import@2.31.0)(eslint@9.15.0) + version: 3.6.3(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.2)) eslint-plugin-import: specifier: 2.31.0 - version: 2.31.0(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + version: 2.31.0(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.2)) eslint-plugin-react: specifier: 7.37.4 - version: 7.37.4(eslint@9.15.0) + version: 7.37.4(eslint@9.15.0(jiti@2.4.2)) eslint-plugin-sort: specifier: 4.0.0 - version: 4.0.0(eslint@9.15.0)(typescript@5.7.2) + version: 4.0.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) globals: specifier: 15.12.0 version: 15.12.0 @@ -276,11 +247,14 @@ importers: version: 5.7.2 typescript-eslint: specifier: 8.16.0 - version: 8.16.0(eslint@9.15.0)(typescript@5.7.2) + version: 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) devDependencies: '@types/node': specifier: 22.10.0 version: 22.10.0 + eslint-plugin-regexp: + specifier: 2.7.0 + version: 2.7.0(eslint@9.15.0(jiti@2.4.2)) workspaces/schema: dependencies: @@ -321,6 +295,9 @@ importers: workspaces/server: dependencies: + '@fastify/compress': + specifier: 8.0.1 + version: 8.0.1 '@fastify/cookie': specifier: 11.0.2 version: 11.0.2 @@ -1509,6 +1486,9 @@ packages: '@fastify/ajv-compiler@4.0.1': resolution: {integrity: sha512-DxrBdgsjNLP0YM6W5Hd6/Fmj43S8zMKiFJYgi+Ri3htTGAowPVG/tG1wpnWLMjufEnehRivUCKZ1pLDIoZdTuw==} + '@fastify/compress@8.0.1': + resolution: {integrity: sha512-yWNfKhvL4orfN45LKCHCo8Fcsbj1kdNgwyShw2xpdHfzPf4A3MESmgSfUm3TCKQwgqDdrPnLfy1E+3I/DVP+BQ==} + '@fastify/cookie@11.0.2': resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==} @@ -1539,22 +1519,6 @@ packages: '@fastify/swagger@9.4.0': resolution: {integrity: sha512-3hF7asqyNfu41aeDA/ATlIG0RY4XizgaDqPR0nc1Unt3EiXWjkVMiELLaH5WZKNvB4BA/5Wovxdin7N4ii7YHw==} - '@ffmpeg/core@0.12.10': - resolution: {integrity: sha512-dzNplnn2Nxle2c2i2rrDhqcB19q9cglCkWnoMTDN9Q9l3PvdjZWd1HfSPjCNWc/p8Q3CT+Es9fWOR0UhAeYQZA==} - engines: {node: '>=16.x'} - - '@ffmpeg/ffmpeg@0.12.15': - resolution: {integrity: sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==} - engines: {node: '>=18.x'} - - '@ffmpeg/types@0.12.4': - resolution: {integrity: sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==} - engines: {node: '>=16.x'} - - '@ffmpeg/util@0.12.2': - resolution: {integrity: sha512-ouyoW+4JB7WxjeZ2y6KpRvB+dLp7Cp4ro8z0HIVpZVCM7AwFlHa0c4R8Y/a4M3wMqATpYKhC7lSFHQ0T11MEDw==} - engines: {node: '>=18.x'} - '@floating-ui/core@1.6.9': resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} @@ -1748,6 +1712,10 @@ packages: '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + '@quansync/fs@0.1.2': + resolution: {integrity: sha512-ezIadUb1aFhwJLd++WVqVpi9rnlX8vnd4ju7saPhwLHJN1mJgOv0puePTGV+FbtSnWtwoHDT8lAm4kagDZmpCg==} + engines: {node: '>=20.0.0'} + '@radix-ui/number@1.1.0': resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} @@ -2115,50 +2083,99 @@ packages: resolution: {integrity: sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@unocss/core@66.1.0-beta.5': - resolution: {integrity: sha512-1kZzSrB87KKd+xP+vMN7IP03j2UPEykna447aw3UaK5RYTDd/LuVtxoep6gvjN9TJiB4K+Qx0sAtgnfhPpka9Q==} + '@unocss/astro@66.1.0-beta.10': + resolution: {integrity: sha512-PDg1n4TeovElo4IqUpqNQA4K5pbLmgPceh8vjs6hUGmH3mwOdTYKYTWtcc2hFy40/6XSaKy0iiWuBogCyVU/EQ==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 + peerDependenciesMeta: + vite: + optional: true + + '@unocss/cli@66.1.0-beta.10': + resolution: {integrity: sha512-B0E5W+xKhixQRIQWcFulmoFn7/KNMv7rLtP/ab3ltZ0Szw9Q+9I0WZIpW4UZmfHOIF7yqqnXxcUIhLvg6Ot3fQ==} + engines: {node: '>=14'} + hasBin: true + + '@unocss/config@66.1.0-beta.10': + resolution: {integrity: sha512-+qx4zlVA9f1cCifoVXYmiHTI1y1rIxHgpiUdb0pI8OOdFsK6j0adua/hSdlvroXAoj2MNdE8WVEEv3L6MlDOpg==} + engines: {node: '>=14'} - '@unocss/extractor-arbitrary-variants@66.1.0-beta.5': - resolution: {integrity: sha512-GBar8cjd+USjgpKy+fgjJK56DdEMfrq1jfa/Sf4UopkuNIatfn6y5ISLI/6E/V52RYVgD2djL7eT8bPDlCDyqA==} + '@unocss/core@66.1.0-beta.10': + resolution: {integrity: sha512-zYn5kmrmmaEQ81+CkoRcNYaMgUePb85RCIr3oty3yc4tFtJHymHuv+4NKoWWZzfhdfVKeK2y7U9wpLcfcbIiew==} - '@unocss/preset-attributify@66.1.0-beta.5': - resolution: {integrity: sha512-jH9cxgrtJHW57mhqYa5kirD+dxxnyP0IU34cs5Y+9syA2lhLFlURVzg7WyJ9dolajlF//ArDEl87TWPXRnHs+w==} + '@unocss/extractor-arbitrary-variants@66.1.0-beta.10': + resolution: {integrity: sha512-qxeScl5guWtlNNUxcOFI12WTLkivao/4vIJW2uJfxuDVlUlBtrB6dw/SL40CVlosZemvM24Boo4U/xjWeh/oCA==} - '@unocss/preset-icons@66.1.0-beta.5': - resolution: {integrity: sha512-800qE/csJOZaiXRvcyMdBqSnJH2eM2757u8RwNLGHDoxCMpmfjdjfTT+yXv1tJV94XlQfuSmSqpbfBIYQkAEIw==} + '@unocss/inspector@66.1.0-beta.10': + resolution: {integrity: sha512-zAFrpQkzNz4uWxynVsnRdIBckVYHafYqUBzIVfuvwcK3rxHhkET5fVGQk70ww29CRX0bjy7x64wPggKsQ2wg2A==} - '@unocss/preset-mini@66.1.0-beta.5': - resolution: {integrity: sha512-1SJbHE6rPou7bi8h+CKozZeBhYIPHr8lLCE30j66y1Vutgt3FI+Je6qT6m9wX2Iql3r2jJMLaXZ3MMA26PKWEQ==} + '@unocss/postcss@66.1.0-beta.10': + resolution: {integrity: sha512-MYbdqNozge5MY/cKO9A7b1WWef7Xw9GiwPWu+RpmBs7218dfowtfIIYzVyLEKWNoFW3iy5JjVm0oYfYCBKj9wg==} + engines: {node: '>=14'} - '@unocss/preset-uno@66.1.0-beta.5': - resolution: {integrity: sha512-EkYHQKhzAcKGw56uZDZux6Sg6hXH7DGPkDGMp5dwY8oLhCAP0TZTw3Jc2FBujEZOa27PO5JLihte0sVMJdHQgg==} + '@unocss/preset-attributify@66.1.0-beta.10': + resolution: {integrity: sha512-Rue15+sGta598wezB9NEcKiLmBFNjaAiPYCsVUU2+3RrrF/H59Uq9RBgQ/9SDn9wCT+mxYcn/aIDaIQzDog1Tg==} - '@unocss/preset-wind3@66.1.0-beta.5': - resolution: {integrity: sha512-+O+Ts60QRe5tpJ9JQbBdLVQFzqiXE/1J3twQ/S5yQeBWUDOIhaEcF2au6nFgdh0MFjXEBk89Ad93Yew78BoMSQ==} + '@unocss/preset-icons@66.1.0-beta.10': + resolution: {integrity: sha512-Ms5CawV26GNi5iN/l9eIohKLcqh5QCA8F5cgJs5zW3kQ31YorveOOyg3QTpHAC4Dln5sZ9/4RplAWObGr2ppiQ==} - '@unocss/reset@66.1.0-beta.5': - resolution: {integrity: sha512-KMRC280hSTo235FdwAmzobLKYWYWVMpUIUuKmtuOXdDg7mXxSjHPbccDW76iwGtRXl8mTt/gL3stVjHgUsfnBA==} + '@unocss/preset-mini@66.1.0-beta.10': + resolution: {integrity: sha512-KqYstZZnOTHvMWAt3Q0UgZipDvvcbYyjpkbSD4Ki8nzHNjF9OJnQHqGTfxvjbiw5Yl27wcB0v4ueOksMENhRrA==} - '@unocss/rule-utils@66.1.0-beta.5': - resolution: {integrity: sha512-G757sAnQAMNRUijgOTut8UkbkncSablI6Viwcq2VP4r0Lhi6RFOv/n6AOTWsDgGeUSuWTa/p3zb3NDHY7ztE9g==} + '@unocss/preset-tagify@66.1.0-beta.10': + resolution: {integrity: sha512-x71VI/PEUxihv8tAXnoPmq40Ysit6aAtslgTaUwy0smhfQfsM4uSC0c8BTrc1R0wZ8JSz+KIb6TbZNMvP52uvQ==} + + '@unocss/preset-typography@66.1.0-beta.10': + resolution: {integrity: sha512-e74Uwy+0croYtvVOEGmQrPz6TAIX1QtMzh2Ngfq283zxg6Cy2PybvdXCa5mUqn9X76pPXs0sWvSo2fknFg/Gjw==} + + '@unocss/preset-uno@66.1.0-beta.10': + resolution: {integrity: sha512-HzB5QB5KRmyZ8JVzLv4ZHMIPvSu7s9q+jb47W4gPJ0fhXUNJ7oVJIVPcYzBz+ppk98uNbUqOkJrnNE5BtUsiVg==} + + '@unocss/preset-web-fonts@66.1.0-beta.10': + resolution: {integrity: sha512-yoXedApMV/TDNG2uLcl4awXs4uYs2isnXmSJabR32DIctknqXfHjzvpEoBz8e1AmlmBz4GEi0i1ounu8mL5nrw==} + + '@unocss/preset-wind3@66.1.0-beta.10': + resolution: {integrity: sha512-R8cp1FORCMTNbIT6UTPIVZfSk62Ns+KrjI8psGzZLhIpbrD57l5CixJKESHGP+Gwp8Ff94PLI9i547ZNT0oMKg==} + + '@unocss/preset-wind4@66.1.0-beta.10': + resolution: {integrity: sha512-MsxnYRkbRy3Sji8DUziKCHeqTNHhPyis7nLxZ63NYOS5fpvkfi4Rh69zus304a4/7rxH5BBJZrlLN7DH4IizgQ==} + + '@unocss/preset-wind@66.1.0-beta.10': + resolution: {integrity: sha512-JZItGFJTCyB9cjuM5YGtqlZQlbjqq0YSUvJU8BDLksoBw/o4hlFNSGnVfFKY9NM9s0NdA4bQWxlNLS9uLROIUw==} + + '@unocss/reset@66.1.0-beta.10': + resolution: {integrity: sha512-B3Xd1jjtzsifpeoFWrtKO+7yjdx0S/lHaaDtAoPxHe8RmQBbjFSWpVV7ohRCEzuZwG0gLJHh5lV+lP70CyFJaw==} + + '@unocss/rule-utils@66.1.0-beta.10': + resolution: {integrity: sha512-yGC8uQT6ErjLsWMU3Nx7mjvftYukLL+TELM+pmYOFmbhasrdnnJI1kT/04dyUHQTlm3XCs8I7LhbYaVz7MmIXA==} engines: {node: '>=14'} - '@unocss/runtime@66.1.0-beta.5': - resolution: {integrity: sha512-K+nDn6yIve2Ied/rz2diFdNDkmAX29CfWik7/PqbLHsTEle2hY+CYvPd3mQZRwGVwIJV2jbxt75r0KXZpbBTxQ==} + '@unocss/transformer-attributify-jsx@66.1.0-beta.10': + resolution: {integrity: sha512-CiqpzJG3bhIMK/bNz8yX3HVv5rqIiXZZ+jqlyfHuioYomUp/Kogk8aQGId2yjJzIxCYKJIu2SlXqgIq3OqiZIQ==} - '@videojs/http-streaming@3.16.2': - resolution: {integrity: sha512-fvt4ko7FknxiT9FnjyNQt6q2px+awrkM+Orv7IB/4gldvj94u4fowGfmNHynnvNTPgPkdxHklGmFLGfclYw8HA==} - engines: {node: '>=8', npm: '>=5'} + '@unocss/transformer-compile-class@66.1.0-beta.10': + resolution: {integrity: sha512-6mdrgypeW7DfkcFQXuoi73bARvwv3lVgqXP3qcw2NZp3qrSjNXoWTlVG8wTmZlA3yibVkUQHKm/ss7wZMArnGg==} + + '@unocss/transformer-directives@66.1.0-beta.10': + resolution: {integrity: sha512-PVXVblXCVo6mjThQrTwHcoNuZvrxjkzW4qWzZQxrCiS+pQs31kod0UL9WFIUWc/xgyRgYUiLNlBBhdxDykNJjg==} + + '@unocss/transformer-variant-group@66.1.0-beta.10': + resolution: {integrity: sha512-S6a5qVZXBv6QxKX7y9hVTUhMseyWEqvLv/p6gkKGAlmnJfeQak8OZBAECHUIhiGzYltF3I8gjsRqx7XYy3yh+w==} + + '@unocss/vite@66.1.0-beta.10': + resolution: {integrity: sha512-d0qHzjOucy4AjAbQmCoFyoY4JjFaGOfhGyerSzzU4/DjOhjUmxsO6KTaDrmAgMGErGegWVoxScxOVCEMuh1c/Q==} peerDependencies: - video.js: ^8.19.0 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 + + '@unocss/webpack@66.1.0-beta.10': + resolution: {integrity: sha512-LWCoulFqeXNpZlU1apXdjX+3ntLeCq9ZEc/k1L/khrxNq6+OQBGM1yo1kTkI8FsaljsdrxAz9bjXspQe4qSKjA==} + peerDependencies: + webpack: ^4 || ^5 '@videojs/vhs-utils@4.1.1': resolution: {integrity: sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==} engines: {node: '>=8', npm: '>=5'} - '@videojs/xhr@2.7.0': - resolution: {integrity: sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==} - '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -2229,10 +2246,6 @@ packages: webpack-dev-server: optional: true - '@xmldom/xmldom@0.8.10': - resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} - engines: {node: '>=10.0.0'} - '@xobotyi/scrollbar-width@1.9.5': resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} @@ -2251,6 +2264,10 @@ packages: abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} @@ -2272,8 +2289,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - aes-decrypter@4.0.2: - resolution: {integrity: sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==} + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} @@ -2428,6 +2447,9 @@ packages: resolution: {integrity: sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==} engines: {node: '>= 16'} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + batch@0.6.1: resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} @@ -2471,6 +2493,9 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -2479,6 +2504,10 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -2554,6 +2583,10 @@ packages: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} @@ -2578,6 +2611,10 @@ packages: resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} engines: {node: '>=0.8'} + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} @@ -2609,9 +2646,6 @@ packages: core-js-compat@3.39.0: resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==} - core-js@3.41.0: - resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} - core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -2622,10 +2656,31 @@ packages: css-in-js-utils@3.1.0: resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} + css-loader@7.1.2: + resolution: {integrity: sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.27.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + css-tree@1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -2645,6 +2700,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -2713,6 +2771,9 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -2874,6 +2935,12 @@ packages: duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + duplexify@3.7.1: + resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} + + duplexify@4.1.3: + resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -2883,9 +2950,6 @@ packages: electron-to-chromium@1.5.65: resolution: {integrity: sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==} - eme-encryption-scheme-polyfill@2.1.6: - resolution: {integrity: sha512-SmQ8UxDkH/8hrjLo6ASo452hIe4dSJzqKmJyrNsvUciEJNxf4z9hewIwF1k/c7A5uRk4GApavPZ6dgqXqfvegw==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2904,6 +2968,9 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.17.1: resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} @@ -3052,6 +3119,12 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-plugin-regexp@2.7.0: + resolution: {integrity: sha512-U8oZI77SBtH8U3ulZ05iu0qEzIizyEDXd+BWHvyVxTOjGwcDcvy/kEpgFG4DYca2ByRLiVPFZ2GeH7j1pdvZTA==} + engines: {node: ^18 || >=20} + peerDependencies: + eslint: '>=8.44.0' + eslint-plugin-sort@4.0.0: resolution: {integrity: sha512-hmYRklp3SLDjhqcFWf7J9K+yGIVfzgnWpi0EqT7HTQJMGW9LIBXw1dshSoERf8PfelVz5ecpxiN/SJjWlCQtGA==} peerDependencies: @@ -3111,6 +3184,10 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -3212,6 +3289,14 @@ packages: picomatch: optional: true + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -3520,6 +3605,15 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -3628,9 +3722,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-function@1.0.2: - resolution: {integrity: sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==} - is-generator-function@1.0.10: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} engines: {node: '>= 0.4'} @@ -3744,6 +3835,10 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} @@ -3757,6 +3852,10 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsdoc-type-pratt-parser@4.1.0: + resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} + engines: {node: '>=12.0.0'} + jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} @@ -3822,6 +3921,7 @@ packages: libsql@0.4.7: resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==} + cpu: [x64, arm64, wasm32] os: [darwin, linux, win32] lie@3.3.0: @@ -3860,9 +3960,6 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -3895,6 +3992,9 @@ packages: mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -3945,6 +4045,12 @@ packages: min-document@2.19.0: resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} + mini-css-extract-plugin@2.9.2: + resolution: {integrity: sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -3992,10 +4098,6 @@ packages: mockdate@3.0.5: resolution: {integrity: sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==} - mpd-parser@1.3.1: - resolution: {integrity: sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==} - hasBin: true - mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -4010,17 +4112,17 @@ packages: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} hasBin: true - mux.js@7.1.0: - resolution: {integrity: sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==} - engines: {node: '>=8', npm: '>=5'} - hasBin: true - nano-css@5.6.2: resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} peerDependencies: react: '*' react-dom: '*' + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -4185,10 +4287,6 @@ packages: resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-min-delay@4.0.2: - resolution: {integrity: sha512-7hJcTq/MGF5pNHbQ2akrpPy1N43YYlB4RPECDSbPRn4xP/dsgP0I6ls7NvSUQ5k88o+CyATMOrQiZ/PK4aQR9w==} - engines: {node: '>=12'} - p-retry@6.2.1: resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} engines: {node: '>=16.17'} @@ -4246,6 +4344,12 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + peek-stream@1.1.3: + resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -4267,10 +4371,6 @@ packages: resolution: {integrity: sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==} hasBin: true - pkcs7@1.0.4: - resolution: {integrity: sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==} - hasBin: true - pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -4299,6 +4399,41 @@ packages: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.2.0: + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.1: + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4400,6 +4535,12 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + pumpify@2.0.1: + resolution: {integrity: sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -4411,6 +4552,9 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} + quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} + quansync@0.2.8: resolution: {integrity: sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==} @@ -4436,12 +4580,6 @@ packages: peerDependencies: react: ^19.0.0 - react-ellipsis-component@1.1.11: - resolution: {integrity: sha512-7qPeHrqgS241sdIOoNNMQWqWLI04ae7myiau8XvMOFJVWWVVs61FjImht2TViu27PAGaVrejV6x18cLoVIX29w==} - engines: {node: '>=10'} - peerDependencies: - react: '>=16' - react-final-form@6.5.9: resolution: {integrity: sha512-x3XYvozolECp3nIjly+4QqxdjSSWfcnpGEL5K8OBT6xmGrq5kBqbA6+/tOqoom9NwqIPPbxPNsOViFlbKgowbA==} peerDependencies: @@ -4498,6 +4636,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -4510,6 +4652,10 @@ packages: resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} engines: {node: '>= 10.13.0'} + refa@0.12.1: + resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -4527,6 +4673,10 @@ packages: regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + regexp-ast-analysis@0.7.1: + resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + regexp.prototype.flags@1.5.3: resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} engines: {node: '>= 0.4'} @@ -4655,6 +4805,10 @@ packages: resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} engines: {node: '>=0.10.0'} + scslre@0.3.0: + resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} + engines: {node: ^14.0.0 || >=16.0.0} + secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} @@ -4720,9 +4874,6 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - shaka-player@4.12.5: - resolution: {integrity: sha512-jJEkASLivZ0Eqg+sIfBJWCWFDzo2l4rfG1e2y5apqphKbDZaMrSCX0Z/B14epJCfStSAwGqKyuC1D+K3e4xBEg==} - shallow-clone@3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} @@ -4769,6 +4920,10 @@ packages: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} + sockjs@0.3.24: resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} @@ -4782,6 +4937,10 @@ packages: resolution: {integrity: sha512-/HrPQAeeLaa+vbAH/znjuhwUluuiM/zL5XX9kop8UpDgjtyWKt43hGDk2vd/TBdDpzIyzIHVUgmYofzYrAQjew==} hasBin: true + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -4824,6 +4983,9 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -4876,6 +5038,12 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + style-loader@4.0.0: + resolution: {integrity: sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.27.0 + stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} @@ -4940,6 +5108,9 @@ packages: resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} engines: {node: '>=10'} + through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} @@ -4953,6 +5124,10 @@ packages: resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -5054,6 +5229,9 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + unconfig@7.3.1: + resolution: {integrity: sha512-LH5WL+un92tGAzWS87k7LkAfwpMdm7V0IXG2FxEjZz/QxiIW5J5LkcrKQThj0aRz6+h/lFmKI9EUXmK/T0bcrw==} + undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} @@ -5073,10 +5251,30 @@ packages: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} + unocss@66.1.0-beta.10: + resolution: {integrity: sha512-20S2TqwDbjO/DSAphraRpozI4cs29IFR7vIQJwAPk8FiJnW65uN+Pdvf+LMNHJM0Xw+lNQkYX/+O71BEO0eCPg==} + engines: {node: '>=14'} + peerDependencies: + '@unocss/webpack': 66.1.0-beta.10 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 + peerDependenciesMeta: + '@unocss/webpack': + optional: true + vite: + optional: true + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unplugin-utils@0.2.4: + resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==} + engines: {node: '>=18.12.0'} + + unplugin@2.2.2: + resolution: {integrity: sha512-Qp+iiD+qCRnUek+nDoYvtWX7tfnYyXsrOnJ452FRTgOyKmTM7TUJ3l+PLPJOOWPTUyKISKp4isC5JJPSXUjGgw==} + engines: {node: '>=18.12.0'} + update-browserslist-db@1.1.1: resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true @@ -5124,23 +5322,10 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - video.js@8.21.0: - resolution: {integrity: sha512-zcwerRb257QAuWfi8NH9yEX7vrGKFthjfcONmOQ4lxFRpDAbAi+u5LAjCjMWqhJda6zEmxkgdDpOMW3Y21QpXA==} - - videojs-contrib-quality-levels@4.1.0: - resolution: {integrity: sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==} - engines: {node: '>=16', npm: '>=8'} + vue-flow-layout@0.1.1: + resolution: {integrity: sha512-JdgRRUVrN0Y2GosA0M68DEbKlXMqJ7FQgsK8CjQD2vxvNSqAU6PZEpi4cfcTVtfM2GVOMjHo7GKKLbXxOBqDqA==} peerDependencies: - video.js: ^8 - - videojs-font@4.2.0: - resolution: {integrity: sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==} - - videojs-vtt.js@0.15.5: - resolution: {integrity: sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==} - - view-transitions-polyfill@1.0.3: - resolution: {integrity: sha512-o7tiNKAsuqvL0u4Epo/jrSOx7qy1/KH3ajzHsY0GU4zWIOiiC6Pyczyf6QgJneyFKlu8QdcMeCQocUl94R+fvA==} + vue: ^3.4.37 watchpack@2.4.2: resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} @@ -5208,6 +5393,9 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + webpack@5.96.1: resolution: {integrity: sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==} engines: {node: '>=10.13.0'} @@ -5300,6 +5488,10 @@ packages: utf-8-validate: optional: true + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -5319,10 +5511,6 @@ packages: resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} engines: {node: '>=12.20'} - yoctodelay@1.2.0: - resolution: {integrity: sha512-12y/P9MSig9/5BEhBgylss+fkHiCRZCvYR81eH35NW9uw801cvJt31EAV+WOLcwZRZbLiIQl/hxcdXXXFmGvXg==} - engines: {node: '>=4'} - zod-openapi@4.2.0: resolution: {integrity: sha512-lnm1e2X5/Ymox5mYxdspy/y52Hb4rPxG1bcwOuHS+YIpxQNEt9s8G4zo34jm0M3+q71TAxgqzcbPLiBXrsfsGA==} engines: {node: '>=18'} @@ -6327,9 +6515,9 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.15.0)': + '@eslint-community/eslint-utils@4.4.1(eslint@9.15.0(jiti@2.4.2))': dependencies: - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -6376,6 +6564,17 @@ snapshots: ajv-formats: 3.0.1 fast-uri: 3.0.3 + '@fastify/compress@8.0.1': + dependencies: + '@fastify/accept-negotiator': 2.0.0 + fastify-plugin: 5.0.1 + mime-db: 1.52.0 + minipass: 7.1.2 + peek-stream: 1.1.3 + pump: 3.0.2 + pumpify: 2.0.1 + readable-stream: 4.7.0 + '@fastify/cookie@11.0.2': dependencies: cookie: 1.0.2 @@ -6436,16 +6635,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@ffmpeg/core@0.12.10': {} - - '@ffmpeg/ffmpeg@0.12.15': - dependencies: - '@ffmpeg/types': 0.12.4 - - '@ffmpeg/types@0.12.4': {} - - '@ffmpeg/util@0.12.2': {} - '@floating-ui/core@1.6.9': dependencies: '@floating-ui/utils': 0.2.9 @@ -6659,6 +6848,10 @@ snapshots: '@polka/url@1.0.0-next.28': {} + '@quansync/fs@0.1.2': + dependencies: + quansync: 0.2.10 + '@radix-ui/number@1.1.0': {} '@radix-ui/primitive@1.1.1': {} @@ -6965,15 +7158,15 @@ snapshots: dependencies: '@types/node': 22.10.0 - '@typescript-eslint/eslint-plugin@8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2))(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.16.0(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) '@typescript-eslint/scope-manager': 8.16.0 - '@typescript-eslint/type-utils': 8.16.0(eslint@9.15.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.16.0(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/type-utils': 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) + '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.16.0 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -6983,14 +7176,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.16.0(eslint@9.15.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2)': dependencies: '@typescript-eslint/scope-manager': 8.16.0 '@typescript-eslint/types': 8.16.0 '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.16.0 debug: 4.3.7 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -7001,12 +7194,12 @@ snapshots: '@typescript-eslint/types': 8.16.0 '@typescript-eslint/visitor-keys': 8.16.0 - '@typescript-eslint/type-utils@8.16.0(eslint@9.15.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2)': dependencies: '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2) - '@typescript-eslint/utils': 8.16.0(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) debug: 4.3.7 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) ts-api-utils: 1.4.2(typescript@5.7.2) optionalDependencies: typescript: 5.7.2 @@ -7030,13 +7223,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.16.0(eslint@9.15.0)(typescript@5.7.2)': + '@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@2.4.2)) '@typescript-eslint/scope-manager': 8.16.0 '@typescript-eslint/types': 8.16.0 '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2) - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -7047,75 +7240,171 @@ snapshots: '@typescript-eslint/types': 8.16.0 eslint-visitor-keys: 4.2.0 - '@unocss/core@66.1.0-beta.5': {} + '@unocss/astro@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + '@unocss/reset': 66.1.0-beta.10 + '@unocss/vite': 66.1.0-beta.10 + transitivePeerDependencies: + - vue + + '@unocss/cli@66.1.0-beta.10': + dependencies: + '@ampproject/remapping': 2.3.0 + '@unocss/config': 66.1.0-beta.10 + '@unocss/core': 66.1.0-beta.10 + '@unocss/preset-uno': 66.1.0-beta.10 + cac: 6.7.14 + chokidar: 3.6.0 + colorette: 2.0.20 + consola: 3.4.2 + magic-string: 0.30.17 + pathe: 2.0.3 + perfect-debounce: 1.0.0 + tinyglobby: 0.2.12 + unplugin-utils: 0.2.4 + + '@unocss/config@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + unconfig: 7.3.1 + + '@unocss/core@66.1.0-beta.10': {} + + '@unocss/extractor-arbitrary-variants@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + + '@unocss/inspector@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + '@unocss/rule-utils': 66.1.0-beta.10 + colorette: 2.0.20 + gzip-size: 6.0.0 + sirv: 3.0.1 + vue-flow-layout: 0.1.1 + transitivePeerDependencies: + - vue - '@unocss/extractor-arbitrary-variants@66.1.0-beta.5': + '@unocss/postcss@66.1.0-beta.10': dependencies: - '@unocss/core': 66.1.0-beta.5 + '@unocss/config': 66.1.0-beta.10 + '@unocss/core': 66.1.0-beta.10 + '@unocss/rule-utils': 66.1.0-beta.10 + css-tree: 3.1.0 + postcss: 8.5.3 + tinyglobby: 0.2.12 - '@unocss/preset-attributify@66.1.0-beta.5': + '@unocss/preset-attributify@66.1.0-beta.10': dependencies: - '@unocss/core': 66.1.0-beta.5 + '@unocss/core': 66.1.0-beta.10 - '@unocss/preset-icons@66.1.0-beta.5': + '@unocss/preset-icons@66.1.0-beta.10': dependencies: '@iconify/utils': 2.3.0 - '@unocss/core': 66.1.0-beta.5 + '@unocss/core': 66.1.0-beta.10 ofetch: 1.4.1 transitivePeerDependencies: - supports-color - '@unocss/preset-mini@66.1.0-beta.5': + '@unocss/preset-mini@66.1.0-beta.10': dependencies: - '@unocss/core': 66.1.0-beta.5 - '@unocss/extractor-arbitrary-variants': 66.1.0-beta.5 - '@unocss/rule-utils': 66.1.0-beta.5 + '@unocss/core': 66.1.0-beta.10 + '@unocss/extractor-arbitrary-variants': 66.1.0-beta.10 + '@unocss/rule-utils': 66.1.0-beta.10 - '@unocss/preset-uno@66.1.0-beta.5': + '@unocss/preset-tagify@66.1.0-beta.10': dependencies: - '@unocss/core': 66.1.0-beta.5 - '@unocss/preset-wind3': 66.1.0-beta.5 + '@unocss/core': 66.1.0-beta.10 - '@unocss/preset-wind3@66.1.0-beta.5': + '@unocss/preset-typography@66.1.0-beta.10': dependencies: - '@unocss/core': 66.1.0-beta.5 - '@unocss/preset-mini': 66.1.0-beta.5 - '@unocss/rule-utils': 66.1.0-beta.5 + '@unocss/core': 66.1.0-beta.10 + '@unocss/preset-mini': 66.1.0-beta.10 + '@unocss/rule-utils': 66.1.0-beta.10 - '@unocss/reset@66.1.0-beta.5': {} + '@unocss/preset-uno@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + '@unocss/preset-wind3': 66.1.0-beta.10 - '@unocss/rule-utils@66.1.0-beta.5': + '@unocss/preset-web-fonts@66.1.0-beta.10': dependencies: - '@unocss/core': 66.1.0-beta.5 + '@unocss/core': 66.1.0-beta.10 + ofetch: 1.4.1 + + '@unocss/preset-wind3@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + '@unocss/preset-mini': 66.1.0-beta.10 + '@unocss/rule-utils': 66.1.0-beta.10 + + '@unocss/preset-wind4@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + '@unocss/extractor-arbitrary-variants': 66.1.0-beta.10 + '@unocss/rule-utils': 66.1.0-beta.10 + + '@unocss/preset-wind@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + '@unocss/preset-wind3': 66.1.0-beta.10 + + '@unocss/reset@66.1.0-beta.10': {} + + '@unocss/rule-utils@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 magic-string: 0.30.17 - '@unocss/runtime@66.1.0-beta.5': + '@unocss/transformer-attributify-jsx@66.1.0-beta.10': dependencies: - '@unocss/core': 66.1.0-beta.5 - '@unocss/preset-attributify': 66.1.0-beta.5 - '@unocss/preset-uno': 66.1.0-beta.5 + '@unocss/core': 66.1.0-beta.10 - '@videojs/http-streaming@3.16.2(video.js@8.21.0)': + '@unocss/transformer-compile-class@66.1.0-beta.10': dependencies: - '@babel/runtime': 7.26.10 - '@videojs/vhs-utils': 4.1.1 - aes-decrypter: 4.0.2 - global: 4.4.0 - m3u8-parser: 7.2.0 - mpd-parser: 1.3.1 - mux.js: 7.1.0 - video.js: 8.21.0 + '@unocss/core': 66.1.0-beta.10 - '@videojs/vhs-utils@4.1.1': + '@unocss/transformer-directives@66.1.0-beta.10': dependencies: - '@babel/runtime': 7.26.10 - global: 4.4.0 + '@unocss/core': 66.1.0-beta.10 + '@unocss/rule-utils': 66.1.0-beta.10 + css-tree: 3.1.0 + + '@unocss/transformer-variant-group@66.1.0-beta.10': + dependencies: + '@unocss/core': 66.1.0-beta.10 + + '@unocss/vite@66.1.0-beta.10': + dependencies: + '@ampproject/remapping': 2.3.0 + '@unocss/config': 66.1.0-beta.10 + '@unocss/core': 66.1.0-beta.10 + '@unocss/inspector': 66.1.0-beta.10 + chokidar: 3.6.0 + magic-string: 0.30.17 + tinyglobby: 0.2.12 + unplugin-utils: 0.2.4 + transitivePeerDependencies: + - vue - '@videojs/xhr@2.7.0': + '@unocss/webpack@66.1.0-beta.10(webpack@5.96.1)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@unocss/config': 66.1.0-beta.10 + '@unocss/core': 66.1.0-beta.10 + chokidar: 3.6.0 + magic-string: 0.30.17 + tinyglobby: 0.2.12 + unplugin: 2.2.2 + unplugin-utils: 0.2.4 + webpack: 5.96.1(webpack-cli@5.1.4) + webpack-sources: 3.2.3 + + '@videojs/vhs-utils@4.1.1': dependencies: '@babel/runtime': 7.26.10 global: 4.4.0 - is-function: 1.0.2 '@webassemblyjs/ast@1.14.1': dependencies: @@ -7210,8 +7499,6 @@ snapshots: optionalDependencies: webpack-dev-server: 5.1.0(webpack-cli@5.1.4)(webpack@5.96.1) - '@xmldom/xmldom@0.8.10': {} - '@xobotyi/scrollbar-width@1.9.5': {} '@xtuc/ieee754@1.2.0': {} @@ -7226,6 +7513,10 @@ snapshots: abbrev@1.1.1: {} + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + abstract-logging@2.0.1: {} accepts@1.3.8: @@ -7243,12 +7534,7 @@ snapshots: acorn@8.14.0: {} - aes-decrypter@4.0.2: - dependencies: - '@babel/runtime': 7.26.10 - '@videojs/vhs-utils': 4.1.1 - global: 4.4.0 - pkcs7: 1.0.4 + acorn@8.14.1: {} agent-base@6.0.2: dependencies: @@ -7440,6 +7726,8 @@ snapshots: balanced-match@3.0.1: {} + base64-js@1.5.1: {} + batch@0.6.1: {} bcrypt@5.1.1: @@ -7502,12 +7790,19 @@ snapshots: buffer-from@1.1.2: {} + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 bytes@3.1.2: {} + cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -7584,6 +7879,8 @@ snapshots: commander@7.2.0: {} + comment-parser@1.4.1: {} + common-path-prefix@3.0.0: {} compressible@2.0.18: @@ -7610,6 +7907,8 @@ snapshots: connect-history-api-fallback@2.0.0: {} + consola@3.4.2: {} + console-control-strings@1.1.0: {} content-disposition@0.5.4: @@ -7634,8 +7933,6 @@ snapshots: dependencies: browserslist: 4.24.2 - core-js@3.41.0: {} - core-util-is@1.0.3: {} cross-spawn@7.0.6: @@ -7648,11 +7945,31 @@ snapshots: dependencies: hyphenate-style-name: 1.1.0 + css-loader@7.1.2(webpack@5.96.1): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.3) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.3) + postcss-modules-scope: 3.2.1(postcss@8.5.3) + postcss-modules-values: 4.0.0(postcss@8.5.3) + postcss-value-parser: 4.2.0 + semver: 7.6.3 + optionalDependencies: + webpack: 5.96.1(webpack-cli@5.1.4) + css-tree@1.1.3: dependencies: mdn-data: 2.0.14 source-map: 0.6.1 + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + + cssesc@3.0.0: {} + csstype@3.1.3: {} data-uri-to-buffer@4.0.1: {} @@ -7675,6 +7992,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dayjs@1.11.13: {} + debounce@1.2.1: {} debug@2.6.9: @@ -7718,6 +8037,8 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + defu@6.1.4: {} + delegates@1.0.0: {} depd@1.1.2: {} @@ -7780,14 +8101,26 @@ snapshots: duplexer@0.1.2: {} + duplexify@3.7.1: + dependencies: + end-of-stream: 1.4.4 + inherits: 2.0.4 + readable-stream: 2.3.8 + stream-shift: 1.0.3 + + duplexify@4.1.3: + dependencies: + end-of-stream: 1.4.4 + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-shift: 1.0.3 + eastasianwidth@0.2.0: {} ee-first@1.1.1: {} electron-to-chromium@1.5.65: {} - eme-encryption-scheme-polyfill@2.1.6: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -7798,6 +8131,10 @@ snapshots: encodeurl@2.0.0: {} + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 @@ -8014,9 +8351,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@9.1.0(eslint@9.15.0): + eslint-config-prettier@9.1.0(eslint@9.15.0(jiti@2.4.2)): dependencies: - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) eslint-import-resolver-node@0.3.9: dependencies: @@ -8026,36 +8363,36 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(eslint-plugin-import@2.31.0)(eslint@9.15.0): + eslint-import-resolver-typescript@3.6.3(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7 enhanced-resolve: 5.17.1 - eslint: 9.15.0 - eslint-module-utils: 2.12.0(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + eslint: 9.15.0(jiti@2.4.2) + eslint-module-utils: 2.12.0(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.2)) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + eslint-plugin-import: 2.31.0(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.2)) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0): + eslint-module-utils@2.12.0(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(eslint-plugin-import@2.31.0)(eslint@9.15.0) + eslint-import-resolver-typescript: 3.6.3(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0): + eslint-plugin-import@2.31.0(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.2)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -8064,9 +8401,9 @@ snapshots: array.prototype.flatmap: 1.3.2 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + eslint-module-utils: 2.12.0(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -8082,7 +8419,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-react@7.37.4(eslint@9.15.0): + eslint-plugin-react@7.37.4(eslint@9.15.0(jiti@2.4.2)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -8090,7 +8427,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.2) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -8104,10 +8441,21 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-sort@4.0.0(eslint@9.15.0)(typescript@5.7.2): + eslint-plugin-regexp@2.7.0(eslint@9.15.0(jiti@2.4.2)): dependencies: - '@typescript-eslint/utils': 8.16.0(eslint@9.15.0)(typescript@5.7.2) - eslint: 9.15.0 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + comment-parser: 1.4.1 + eslint: 9.15.0(jiti@2.4.2) + jsdoc-type-pratt-parser: 4.1.0 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + scslre: 0.3.0 + + eslint-plugin-sort@4.0.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2): + dependencies: + '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) + eslint: 9.15.0(jiti@2.4.2) isomorphic-resolve: 1.0.0 natural-compare: 1.4.0 transitivePeerDependencies: @@ -8128,9 +8476,9 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.15.0: + eslint@9.15.0(jiti@2.4.2): dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@2.4.2)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.19.0 '@eslint/core': 0.9.0 @@ -8164,6 +8512,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 transitivePeerDependencies: - supports-color @@ -8189,6 +8539,8 @@ snapshots: etag@1.8.1: {} + event-target-shim@5.0.1: {} + eventemitter3@4.0.7: {} events@3.3.0: {} @@ -8326,6 +8678,10 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + fetch-blob@3.2.0: dependencies: node-domexception: 1.0.0 @@ -8655,6 +9011,12 @@ snapshots: dependencies: safer-buffer: 2.1.2 + icss-utils@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + ieee754@1.2.1: {} + ignore@5.3.2: {} immediate@3.0.6: {} @@ -8752,8 +9114,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-function@1.0.2: {} - is-generator-function@1.0.10: dependencies: has-tostringtag: 1.0.2 @@ -8861,6 +9221,8 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 + jiti@2.4.2: {} + js-base64@3.7.7: {} js-cookie@2.2.1: {} @@ -8871,6 +9233,8 @@ snapshots: dependencies: argparse: 2.0.1 + jsdoc-type-pratt-parser@4.1.0: {} + jsesc@3.0.2: {} json-buffer@3.0.1: {} @@ -8988,8 +9352,6 @@ snapshots: lodash.merge@4.6.2: {} - lodash@4.17.21: {} - loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -9019,6 +9381,8 @@ snapshots: mdn-data@2.0.14: {} + mdn-data@2.12.2: {} + media-typer@0.3.0: {} memfs@4.14.0: @@ -9057,6 +9421,12 @@ snapshots: dependencies: dom-walk: 0.1.2 + mini-css-extract-plugin@2.9.2(webpack@5.96.1): + dependencies: + schema-utils: 4.2.0 + tapable: 2.2.1 + webpack: 5.96.1(webpack-cli@5.1.4) + minimalistic-assert@1.0.1: {} minimatch@10.0.1: @@ -9101,13 +9471,6 @@ snapshots: mockdate@3.0.5: {} - mpd-parser@1.3.1: - dependencies: - '@babel/runtime': 7.26.10 - '@videojs/vhs-utils': 4.1.1 - '@xmldom/xmldom': 0.8.10 - global: 4.4.0 - mrmime@2.0.1: {} ms@2.0.0: {} @@ -9119,11 +9482,6 @@ snapshots: dns-packet: 5.6.1 thunky: 1.1.0 - mux.js@7.1.0: - dependencies: - '@babel/runtime': 7.26.10 - global: 4.4.0 - nano-css@5.6.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -9137,6 +9495,8 @@ snapshots: stacktrace-js: 2.0.2 stylis: 4.3.6 + nanoid@3.3.11: {} + natural-compare@1.4.0: {} negotiator@0.6.3: {} @@ -9305,10 +9665,6 @@ snapshots: dependencies: p-limit: 4.0.0 - p-min-delay@4.0.2: - dependencies: - yoctodelay: 1.2.0 - p-retry@6.2.1: dependencies: '@types/retry': 0.12.2 @@ -9352,6 +9708,14 @@ snapshots: pathe@2.0.3: {} + peek-stream@1.1.3: + dependencies: + buffer-from: 1.1.2 + duplexify: 3.7.1 + through2: 2.0.5 + + perfect-debounce@1.0.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -9378,10 +9742,6 @@ snapshots: sonic-boom: 4.2.0 thread-stream: 3.1.0 - pkcs7@1.0.4: - dependencies: - '@babel/runtime': 7.26.10 - pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -9412,6 +9772,40 @@ snapshots: possible-typed-array-names@1.0.0: {} + postcss-modules-extract-imports@3.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-modules-local-by-default@4.2.0(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 7.1.0 + + postcss-modules-values@4.0.0(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.3: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prelude-ls@1.2.1: {} prettier-plugin-packagejson@2.5.6(prettier@3.4.0): @@ -9456,6 +9850,17 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + pumpify@2.0.1: + dependencies: + duplexify: 4.1.3 + inherits: 2.0.4 + pump: 3.0.2 + punycode@2.3.1: {} pure-rand@6.1.0: {} @@ -9464,6 +9869,8 @@ snapshots: dependencies: side-channel: 1.0.6 + quansync@0.2.10: {} + quansync@0.2.8: {} queue-microtask@1.2.3: {} @@ -9488,11 +9895,6 @@ snapshots: react: 19.0.0 scheduler: 0.25.0 - react-ellipsis-component@1.1.11(react@19.0.0): - dependencies: - react: 19.0.0 - resize-observer-polyfill: 1.5.1 - react-final-form@6.5.9(final-form@4.20.10)(react@19.0.0): dependencies: '@babel/runtime': 7.26.10 @@ -9566,6 +9968,14 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -9576,6 +9986,10 @@ snapshots: dependencies: resolve: 1.22.8 + refa@0.12.1: + dependencies: + '@eslint-community/regexpp': 4.12.1 + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -9599,6 +10013,11 @@ snapshots: dependencies: '@babel/runtime': 7.26.10 + regexp-ast-analysis@0.7.1: + dependencies: + '@eslint-community/regexpp': 4.12.1 + refa: 0.12.1 + regexp.prototype.flags@1.5.3: dependencies: call-bind: 1.0.8 @@ -9723,6 +10142,12 @@ snapshots: screenfull@5.2.0: {} + scslre@0.3.0: + dependencies: + '@eslint-community/regexpp': 4.12.1 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + secure-json-parse@2.7.0: {} select-hose@2.0.0: {} @@ -9813,10 +10238,6 @@ snapshots: setprototypeof@1.2.0: {} - shaka-player@4.12.5(patch_hash=ztcamgtqc3a62la4l6p3d6w4ae): - dependencies: - eme-encryption-scheme-polyfill: 2.1.6 - shallow-clone@3.0.1: dependencies: kind-of: 6.0.3 @@ -9874,6 +10295,12 @@ snapshots: mrmime: 2.0.1 totalist: 3.0.1 + sirv@3.0.1: + dependencies: + '@polka/url': 1.0.0-next.28 + mrmime: 2.0.1 + totalist: 3.0.1 + sockjs@0.3.24: dependencies: faye-websocket: 0.11.4 @@ -9897,6 +10324,8 @@ snapshots: sort-object-keys: 1.1.3 tinyglobby: 0.2.10 + source-map-js@1.2.1: {} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 @@ -9950,6 +10379,8 @@ snapshots: statuses@2.0.1: {} + stream-shift@1.0.3: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -10032,6 +10463,10 @@ snapshots: strip-json-comments@3.1.1: {} + style-loader@4.0.0(webpack@5.96.1): + dependencies: + webpack: 5.96.1(webpack-cli@5.1.4) + stylis@4.3.6: {} supports-color@7.2.0: @@ -10088,6 +10523,11 @@ snapshots: throttle-debounce@3.0.1: {} + through2@2.0.5: + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + thunky@1.1.0: {} tiny-invariant@1.3.3: {} @@ -10099,6 +10539,11 @@ snapshots: fdir: 6.4.2(picomatch@4.0.2) picomatch: 4.0.2 + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -10185,12 +10630,12 @@ snapshots: possible-typed-array-names: 1.0.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.16.0(eslint@9.15.0)(typescript@5.7.2): + typescript-eslint@8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.16.0(eslint@9.15.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.16.0(eslint@9.15.0)(typescript@5.7.2) - eslint: 9.15.0 + '@typescript-eslint/eslint-plugin': 8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2))(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) + '@typescript-eslint/parser': 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) + '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@2.4.2))(typescript@5.7.2) + eslint: 9.15.0(jiti@2.4.2) optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -10207,6 +10652,13 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + unconfig@7.3.1: + dependencies: + '@quansync/fs': 0.1.2 + defu: 6.1.4 + jiti: 2.4.2 + quansync: 0.2.8 + undici-types@6.20.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} @@ -10220,8 +10672,45 @@ snapshots: unicode-property-aliases-ecmascript@2.1.0: {} + unocss@66.1.0-beta.10(@unocss/webpack@66.1.0-beta.10(webpack@5.96.1)): + dependencies: + '@unocss/astro': 66.1.0-beta.10 + '@unocss/cli': 66.1.0-beta.10 + '@unocss/core': 66.1.0-beta.10 + '@unocss/postcss': 66.1.0-beta.10 + '@unocss/preset-attributify': 66.1.0-beta.10 + '@unocss/preset-icons': 66.1.0-beta.10 + '@unocss/preset-mini': 66.1.0-beta.10 + '@unocss/preset-tagify': 66.1.0-beta.10 + '@unocss/preset-typography': 66.1.0-beta.10 + '@unocss/preset-uno': 66.1.0-beta.10 + '@unocss/preset-web-fonts': 66.1.0-beta.10 + '@unocss/preset-wind': 66.1.0-beta.10 + '@unocss/preset-wind3': 66.1.0-beta.10 + '@unocss/preset-wind4': 66.1.0-beta.10 + '@unocss/transformer-attributify-jsx': 66.1.0-beta.10 + '@unocss/transformer-compile-class': 66.1.0-beta.10 + '@unocss/transformer-directives': 66.1.0-beta.10 + '@unocss/transformer-variant-group': 66.1.0-beta.10 + '@unocss/vite': 66.1.0-beta.10 + optionalDependencies: + '@unocss/webpack': 66.1.0-beta.10(webpack@5.96.1) + transitivePeerDependencies: + - supports-color + - vue + unpipe@1.0.0: {} + unplugin-utils@0.2.4: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.2 + + unplugin@2.2.2: + dependencies: + acorn: 8.14.1 + webpack-virtual-modules: 0.6.2 + update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: browserslist: 4.24.2 @@ -10255,33 +10744,7 @@ snapshots: vary@1.1.2: {} - video.js@8.21.0: - dependencies: - '@babel/runtime': 7.26.10 - '@videojs/http-streaming': 3.16.2(video.js@8.21.0) - '@videojs/vhs-utils': 4.1.1 - '@videojs/xhr': 2.7.0 - aes-decrypter: 4.0.2 - global: 4.4.0 - m3u8-parser: 7.2.0 - mpd-parser: 1.3.1 - mux.js: 7.1.0 - videojs-contrib-quality-levels: 4.1.0(video.js@8.21.0) - videojs-font: 4.2.0 - videojs-vtt.js: 0.15.5 - - videojs-contrib-quality-levels@4.1.0(video.js@8.21.0): - dependencies: - global: 4.4.0 - video.js: 8.21.0 - - videojs-font@4.2.0: {} - - videojs-vtt.js@0.15.5: - dependencies: - global: 4.4.0 - - view-transitions-polyfill@1.0.3: {} + vue-flow-layout@0.1.1: {} watchpack@2.4.2: dependencies: @@ -10392,6 +10855,8 @@ snapshots: webpack-sources@3.2.3: {} + webpack-virtual-modules@0.6.2: {} + webpack@5.96.1(webpack-cli@5.1.4): dependencies: '@types/eslint-scope': 3.7.7 @@ -10516,6 +10981,8 @@ snapshots: ws@8.18.0: {} + xtend@4.0.2: {} + yallist@3.1.1: {} yallist@4.0.0: {} @@ -10526,8 +10993,6 @@ snapshots: yocto-queue@1.1.1: {} - yoctodelay@1.2.0: {} - zod-openapi@4.2.0(zod@3.24.1): dependencies: zod: 3.24.1 diff --git a/public/animations/001.gif b/public/animations/001.gif deleted file mode 100644 index a047ac0a9..000000000 Binary files a/public/animations/001.gif and /dev/null differ diff --git a/public/animations/001.mp4 b/public/animations/001.mp4 new file mode 100644 index 000000000..dd38b4305 Binary files /dev/null and b/public/animations/001.mp4 differ diff --git a/public/images/thumbnails/caminandes2/preview.jpg b/public/images/thumbnails/caminandes2/preview.jpg new file mode 100644 index 000000000..b6f0dc969 Binary files /dev/null and b/public/images/thumbnails/caminandes2/preview.jpg differ diff --git a/public/images/thumbnails/dailydweebs/preview.jpg b/public/images/thumbnails/dailydweebs/preview.jpg new file mode 100644 index 000000000..c292eac77 Binary files /dev/null and b/public/images/thumbnails/dailydweebs/preview.jpg differ diff --git a/public/images/thumbnails/glasshalf/preview.jpg b/public/images/thumbnails/glasshalf/preview.jpg new file mode 100644 index 000000000..c3b1e087b Binary files /dev/null and b/public/images/thumbnails/glasshalf/preview.jpg differ diff --git a/public/images/thumbnails/wing-it/preview.jpg b/public/images/thumbnails/wing-it/preview.jpg new file mode 100644 index 000000000..076bfa996 Binary files /dev/null and b/public/images/thumbnails/wing-it/preview.jpg differ diff --git a/workspaces/client/.gitignore b/workspaces/client/.gitignore new file mode 100644 index 000000000..497d5825b --- /dev/null +++ b/workspaces/client/.gitignore @@ -0,0 +1 @@ +stats.json diff --git a/workspaces/client/analyze_bundle.sh b/workspaces/client/analyze_bundle.sh new file mode 100755 index 000000000..0e2c8d94c --- /dev/null +++ b/workspaces/client/analyze_bundle.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# デフォルト値の設定 +DEFALT_SIZE="parsed" + +# オプションの処理 +while getopts "s:" opt; do + case $opt in + s) + DEFALT_SIZE="$OPTARG" + ;; + \?) + echo "無効なオプション: -$OPTARG" >&2 + exit 1 + ;; + esac +done + +pnpm run build +npx webpack --profile --json > stats.json +npx webpack-bundle-analyzer stats.json dist -s "$DEFALT_SIZE" diff --git a/workspaces/client/eslint.config.mjs b/workspaces/client/eslint.config.mjs index 01b7f8522..ddd2c73f1 100644 --- a/workspaces/client/eslint.config.mjs +++ b/workspaces/client/eslint.config.mjs @@ -4,5 +4,9 @@ export default [ ...configs, { ignores: ['dist/*', '.wireit/*'], + rules: { + "react/jsx-sort-props": "off", + "regexp/no-unused-capturing-group": "off", + } }, ]; diff --git a/workspaces/client/package.json b/workspaces/client/package.json index f6c261693..82816e69c 100644 --- a/workspaces/client/package.json +++ b/workspaces/client/package.json @@ -12,7 +12,6 @@ "@better-fetch/fetch": "1.1.15", "@dhmk/zustand-lens": "5.0.0", "@epic-web/restore-scroll": "1.1.1", - "@ffmpeg/ffmpeg": "0.12.15", "@headlessui/react": "2.2.0", "@radix-ui/react-slider": "1.2.3", "@standard-schema/spec": "1.0.0", @@ -22,13 +21,9 @@ "classnames": "2.5.1", "final-form": "4.20.10", "immer": "10.1.1", - "lodash": "4.17.21", - "luxon": "3.5.0", "m3u8-parser": "7.2.0", - "p-min-delay": "4.0.2", "react": "19.0.0", "react-dom": "19.0.0", - "react-ellipsis-component": "1.1.11", "react-final-form": "6.5.9", "react-flip-toolkit": "7.2.4", "react-router": "7.0.2", @@ -40,8 +35,6 @@ "use-callback-ref": "1.3.3", "use-sync-external-store": "1.4.0", "valibot": "1.0.0-rc.3", - "view-transitions-polyfill": "1.0.3", - "zod": "3.24.1", "zustand": "5.0.3", "zustand-di": "0.0.16" }, @@ -50,8 +43,6 @@ "@babel/preset-env": "7.26.0", "@babel/preset-react": "7.25.9", "@babel/preset-typescript": "7.26.0", - "@ffmpeg/core": "0.12.10", - "@ffmpeg/util": "0.12.2", "@iconify/json": "2.2.317", "@iconify/types": "2.0.0", "@types/lodash": "4.17.16", @@ -60,18 +51,19 @@ "@types/react": "19.0.1", "@types/react-dom": "19.0.2", "@types/wicg-task-scheduling": "2024.1.0", - "@unocss/preset-icons": "66.1.0-beta.5", - "@unocss/preset-wind3": "66.1.0-beta.5", - "@unocss/reset": "66.1.0-beta.5", - "@unocss/runtime": "66.1.0-beta.5", + "@unocss/preset-wind3": "66.1.0-beta.10", + "@unocss/reset": "66.1.0-beta.10", + "@unocss/webpack": "66.1.0-beta.10", "@wsh-2025/configs": "workspace:*", "arraybuffer-loader": "1.0.8", "babel-loader": "9.2.1", - "core-js": "3.41.0", + "css-loader": "7.1.2", + "dayjs": "1.11.13", "hls.js": "1.5.17", - "shaka-player": "4.12.5", + "mini-css-extract-plugin": "2.9.2", + "style-loader": "4.0.0", "typescript": "5.7.2", - "video.js": "8.21.0", + "unocss": "66.1.0-beta.10", "webpack": "5.96.1", "webpack-bundle-analyzer": "4.10.2", "webpack-cli": "5.1.4", @@ -85,6 +77,7 @@ "../../pnpm-lock.yaml", "../schema/src/**/*", "./src/**/*", + "./uno.config.ts", "./webpack.config.mjs" ], "output": [ diff --git a/workspaces/client/src/app/Document.tsx b/workspaces/client/src/app/Document.tsx index 0ca7b8252..81bb88851 100644 --- a/workspaces/client/src/app/Document.tsx +++ b/workspaces/client/src/app/Document.tsx @@ -15,6 +15,7 @@ export const Document = () => { + diff --git a/workspaces/client/src/app/createRoutes.tsx b/workspaces/client/src/app/createRoutes.tsx index a81e12561..c4ef27252 100644 --- a/workspaces/client/src/app/createRoutes.tsx +++ b/workspaces/client/src/app/createRoutes.tsx @@ -1,4 +1,3 @@ -import lazy from 'p-min-delay'; import { RouteObject } from 'react-router'; import { Document, prefetch } from '@wsh-2025/client/src/app/Document'; @@ -11,10 +10,7 @@ export function createRoutes(store: ReturnType): RouteObject { index: true, async lazy() { - const { HomePage, prefetch } = await lazy( - import('@wsh-2025/client/src/pages/home/components/HomePage'), - 1000, - ); + const { HomePage, prefetch } = await import('@wsh-2025/client/src/pages/home/components/HomePage'); return { Component: HomePage, async loader() { @@ -25,10 +21,7 @@ export function createRoutes(store: ReturnType): RouteObject }, { async lazy() { - const { EpisodePage, prefetch } = await lazy( - import('@wsh-2025/client/src/pages/episode/components/EpisodePage'), - 1000, - ); + const { EpisodePage, prefetch } = await import('@wsh-2025/client/src/pages/episode/components/EpisodePage'); return { Component: EpisodePage, async loader({ params }) { @@ -40,10 +33,7 @@ export function createRoutes(store: ReturnType): RouteObject }, { async lazy() { - const { prefetch, ProgramPage } = await lazy( - import('@wsh-2025/client/src/pages/program/components/ProgramPage'), - 1000, - ); + const { prefetch, ProgramPage } = await import('@wsh-2025/client/src/pages/program/components/ProgramPage'); return { Component: ProgramPage, async loader({ params }) { @@ -55,10 +45,7 @@ export function createRoutes(store: ReturnType): RouteObject }, { async lazy() { - const { prefetch, SeriesPage } = await lazy( - import('@wsh-2025/client/src/pages/series/components/SeriesPage'), - 1000, - ); + const { prefetch, SeriesPage } = await import('@wsh-2025/client/src/pages/series/components/SeriesPage'); return { Component: SeriesPage, async loader({ params }) { @@ -70,9 +57,8 @@ export function createRoutes(store: ReturnType): RouteObject }, { async lazy() { - const { prefetch, TimetablePage } = await lazy( - import('@wsh-2025/client/src/pages/timetable/components/TimetablePage'), - 1000, + const { prefetch, TimetablePage } = await import( + '@wsh-2025/client/src/pages/timetable/components/TimetablePage' ); return { Component: TimetablePage, @@ -85,9 +71,8 @@ export function createRoutes(store: ReturnType): RouteObject }, { async lazy() { - const { NotFoundPage, prefetch } = await lazy( - import('@wsh-2025/client/src/pages/not_found/components/NotFoundPage'), - 1000, + const { NotFoundPage, prefetch } = await import( + '@wsh-2025/client/src/pages/not_found/components/NotFoundPage' ); return { Component: NotFoundPage, diff --git a/workspaces/client/src/app/createStore.ts b/workspaces/client/src/app/createStore.ts index 92d2abaaf..3a4feadb2 100644 --- a/workspaces/client/src/app/createStore.ts +++ b/workspaces/client/src/app/createStore.ts @@ -1,5 +1,4 @@ import { withLenses } from '@dhmk/zustand-lens'; -import _ from 'lodash'; import { createStore as createZustandStore } from 'zustand/vanilla'; import { createAuthStoreSlice } from '@wsh-2025/client/src/features/auth/stores/createAuthStoreSlice'; @@ -14,11 +13,7 @@ import { createEpisodePageStoreSlice } from '@wsh-2025/client/src/pages/episode/ import { createProgramPageStoreSlice } from '@wsh-2025/client/src/pages/program/stores/createProgramPageStoreSlice'; import { createTimetablePageStoreSlice } from '@wsh-2025/client/src/pages/timetable/stores/createTimetablePageStoreSlice'; -interface Props { - hydrationData?: unknown; -} - -export const createStore = ({ hydrationData }: Props) => { +export const createStore = () => { const store = createZustandStore( withLenses(() => ({ features: { @@ -38,8 +33,7 @@ export const createStore = ({ hydrationData }: Props) => { }, })), ); - - store.setState((s) => _.merge(s, hydrationData)); + store.setState((s) => s); return store; }; diff --git a/workspaces/client/src/features/auth/components/SignInDialog.tsx b/workspaces/client/src/features/auth/components/SignInDialog.tsx index 350d89edc..4bd39a20a 100644 --- a/workspaces/client/src/features/auth/components/SignInDialog.tsx +++ b/workspaces/client/src/features/auth/components/SignInDialog.tsx @@ -2,7 +2,7 @@ import { BetterFetchError } from '@better-fetch/fetch'; import { FORM_ERROR } from 'final-form'; import { useId } from 'react'; import { Field, Form } from 'react-final-form'; -import { z } from 'zod'; +import * as v from 'valibot'; import { useAuthActions } from '@wsh-2025/client/src/features/auth/hooks/useAuthActions'; import { isValidEmail } from '@wsh-2025/client/src/features/auth/logics/isValidEmail'; @@ -54,16 +54,29 @@ export const SignInDialog = ({ isOpen, onClose, onOpenSignUp }: Props) => {
{ - const schema = z.object({ - email: z - .string({ required_error: 'メールアドレスを入力してください' }) - .and(z.custom(isValidEmail, { message: 'メールアドレスが正しくありません' })), - password: z - .string({ required_error: 'パスワードを入力してください' }) - .and(z.custom(isValidPassword, { message: 'パスワードが正しくありません' })), + const schema = v.object({ + email: v.optional( + v.pipe( + v.string('メールアドレスを入力してください'), + v.minLength(1, 'メールアドレスを入力してください'), + v.check(isValidEmail, 'メールアドレスが正しくありません'), + ), + ), + password: v.optional( + v.pipe( + v.string('パスワードを入力してください'), + v.minLength(1, 'パスワードを入力してください'), + v.check(isValidPassword, 'パスワードが正しくありません'), + ), + ), }); - const result = schema.safeParse(values); - return result.success ? undefined : result.error.formErrors.fieldErrors; + const result = v.safeParse(schema, values); + if (result.success) { + return undefined; + } else { + const errors = v.flatten(result.issues); + return errors.nested; + } }} onSubmit={onSubmit} > diff --git a/workspaces/client/src/features/auth/components/SignUpDialog.tsx b/workspaces/client/src/features/auth/components/SignUpDialog.tsx index 1cb939f8d..dbb5fe3a1 100644 --- a/workspaces/client/src/features/auth/components/SignUpDialog.tsx +++ b/workspaces/client/src/features/auth/components/SignUpDialog.tsx @@ -2,7 +2,7 @@ import { BetterFetchError } from '@better-fetch/fetch'; import { FORM_ERROR } from 'final-form'; import { useId } from 'react'; import { Field, Form } from 'react-final-form'; -import { z } from 'zod'; +import * as v from 'valibot'; import { useAuthActions } from '@wsh-2025/client/src/features/auth/hooks/useAuthActions'; import { isValidEmail } from '@wsh-2025/client/src/features/auth/logics/isValidEmail'; @@ -54,16 +54,29 @@ export const SignUpDialog = ({ isOpen, onClose, onOpenSignIn }: Props) => { { - const schema = z.object({ - email: z - .string({ required_error: 'メールアドレスを入力してください' }) - .and(z.custom(isValidEmail, { message: 'メールアドレスが正しくありません' })), - password: z - .string({ required_error: 'パスワードを入力してください' }) - .and(z.custom(isValidPassword, { message: 'パスワードが正しくありません' })), + const schema = v.object({ + email: v.optional( + v.pipe( + v.string('メールアドレスを入力してください'), + v.minLength(1, 'メールアドレスを入力してください'), + v.check(isValidEmail, 'メールアドレスが正しくありません'), + ), + ), + password: v.optional( + v.pipe( + v.string('パスワードを入力してください'), + v.minLength(1, 'パスワードを入力してください'), + v.check(isValidPassword, 'パスワードが正しくありません'), + ), + ), }); - const result = schema.safeParse(values); - return result.success ? undefined : result.error.formErrors.fieldErrors; + const result = v.safeParse(schema, values); + if (result.success) { + return undefined; + } else { + const errors = v.flatten(result.issues); + return errors.nested; + } }} onSubmit={onSubmit} > diff --git a/workspaces/client/src/features/auth/logics/isValidEmail.ts b/workspaces/client/src/features/auth/logics/isValidEmail.ts index 72b35dd7d..3cc0e1b58 100644 --- a/workspaces/client/src/features/auth/logics/isValidEmail.ts +++ b/workspaces/client/src/features/auth/logics/isValidEmail.ts @@ -1,3 +1,18 @@ export const isValidEmail = (email: string): boolean => { - return /^([A-Z0-9_+-]+\.?)*[A-Z0-9_+-]@([A-Z0-9][A-Z0-9-]*\.)+[A-Z]{2,}$/i.test(email); + const parts = email.split('@'); + if (parts.length !== 2) { + return false; + } + + const localPart = parts[0] as string; + const domainPart = parts[1] as string; + + if (!/^[\w+-]+(?:\.[\w+-]+)*$/.test(localPart)) { + return false; + } + if (!/^[A-Z0-9-]+(?:\.[A-Z0-9-]+)*\.[A-Z]{2,}$/i.test(domainPart)) { + return false; + } + + return true; }; diff --git a/workspaces/client/src/features/auth/logics/isValidPassword.ts b/workspaces/client/src/features/auth/logics/isValidPassword.ts index 59025dc40..fb722d4ba 100644 --- a/workspaces/client/src/features/auth/logics/isValidPassword.ts +++ b/workspaces/client/src/features/auth/logics/isValidPassword.ts @@ -1,3 +1,3 @@ export const isValidPassword = (password: string): boolean => { - return /^([A-Z0-9_+-]|[A-Z0-9_+-]){3,}$/i.test(password); + return /^[\w+-]{3,}$/.test(password); }; diff --git a/workspaces/client/src/features/auth/services/authService.ts b/workspaces/client/src/features/auth/services/authService.ts index df4c6f0d2..49d1d01eb 100644 --- a/workspaces/client/src/features/auth/services/authService.ts +++ b/workspaces/client/src/features/auth/services/authService.ts @@ -1,26 +1,13 @@ -import { createFetch, createSchema } from '@better-fetch/fetch'; +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +import { createFetch } from '@better-fetch/fetch'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin'; const $fetch = createFetch({ baseURL: process.env['API_BASE_URL'] ?? '/api', plugins: [schedulePlugin], - schema: createSchema({ - '/signIn': { - input: schema.signInRequestBody, - output: schema.signInResponse, - }, - '/signOut': {}, - '/signUp': { - input: schema.signUpRequestBody, - output: schema.signUpResponse, - }, - '/users/me': { - output: schema.getUserResponse, - }, - }), throw: true, }); @@ -37,18 +24,24 @@ interface AuthService { export const authService: AuthService = { async fetchSignIn({ email, password }) { - const data = await $fetch('/signIn', { body: { email, password }, method: 'POST' }); + const data = (await $fetch('/signIn', { + body: { email, password }, + method: 'POST', + })) as StandardSchemaV1.InferOutput; return data; }, async fetchSignOut() { await $fetch('/signOut', { method: 'POST' }); }, async fetchSignUp({ email, password }) { - const data = await $fetch('/signUp', { body: { email, password }, method: 'POST' }); + const data = (await $fetch('/signUp', { + body: { email, password }, + method: 'POST', + })) as StandardSchemaV1.InferOutput; return data; }, async fetchUser() { - const data = await $fetch('/users/me'); + const data = (await $fetch('/users/me')) as StandardSchemaV1.InferOutput; return data; }, }; diff --git a/workspaces/client/src/features/auth/stores/createAuthStoreSlice.ts b/workspaces/client/src/features/auth/stores/createAuthStoreSlice.ts index b8bf797ad..20b160b65 100644 --- a/workspaces/client/src/features/auth/stores/createAuthStoreSlice.ts +++ b/workspaces/client/src/features/auth/stores/createAuthStoreSlice.ts @@ -1,6 +1,6 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { authService } from '../services/authService'; diff --git a/workspaces/client/src/features/channel/services/channelService.ts b/workspaces/client/src/features/channel/services/channelService.ts index 312d08c69..89573611a 100644 --- a/workspaces/client/src/features/channel/services/channelService.ts +++ b/workspaces/client/src/features/channel/services/channelService.ts @@ -1,6 +1,7 @@ -import { createFetch, createSchema } from '@better-fetch/fetch'; +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +import { createFetch } from '@better-fetch/fetch'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import * as batshit from '@yornaath/batshit'; import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin'; @@ -8,22 +9,16 @@ import { schedulePlugin } from '@wsh-2025/client/src/features/requests/scheduleP const $fetch = createFetch({ baseURL: process.env['API_BASE_URL'] ?? '/api', plugins: [schedulePlugin], - schema: createSchema({ - '/channels': { - output: schema.getChannelsResponse, - query: schema.getChannelsRequestQuery, - }, - }), throw: true, }); const batcher = batshit.create({ async fetcher(queries: { channelId: string }[]) { - const data = await $fetch('/channels', { + const data = (await $fetch('/channels', { query: { channelIds: queries.map((q) => q.channelId).join(','), }, - }); + })) as StandardSchemaV1.InferOutput; return data; }, resolver(items, query: { channelId: string }) { @@ -52,7 +47,9 @@ export const channelService: ChannelService = { return channel; }, async fetchChannels() { - const data = await $fetch('/channels', { query: {} }); + const data = (await $fetch('/channels', { query: {} })) as StandardSchemaV1.InferOutput< + typeof schema.getChannelsResponse + >; return data; }, }; diff --git a/workspaces/client/src/features/channel/stores/createChannelStoreSlice.ts b/workspaces/client/src/features/channel/stores/createChannelStoreSlice.ts index 2543d978e..968e0e6d0 100644 --- a/workspaces/client/src/features/channel/stores/createChannelStoreSlice.ts +++ b/workspaces/client/src/features/channel/stores/createChannelStoreSlice.ts @@ -1,6 +1,6 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { produce } from 'immer'; import { channelService } from '@wsh-2025/client/src/features/channel/services/channelService'; diff --git a/workspaces/client/src/features/episode/services/episodeService.ts b/workspaces/client/src/features/episode/services/episodeService.ts index 3a21b8194..a0245db6c 100644 --- a/workspaces/client/src/features/episode/services/episodeService.ts +++ b/workspaces/client/src/features/episode/services/episodeService.ts @@ -1,6 +1,7 @@ -import { createFetch, createSchema } from '@better-fetch/fetch'; +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +import { createFetch } from '@better-fetch/fetch'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import * as batshit from '@yornaath/batshit'; import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin'; @@ -8,25 +9,16 @@ import { schedulePlugin } from '@wsh-2025/client/src/features/requests/scheduleP const $fetch = createFetch({ baseURL: process.env['API_BASE_URL'] ?? '/api', plugins: [schedulePlugin], - schema: createSchema({ - '/episodes': { - output: schema.getEpisodesResponse, - query: schema.getEpisodesRequestQuery, - }, - '/episodes/:episodeId': { - output: schema.getEpisodeByIdResponse, - }, - }), throw: true, }); const batcher = batshit.create({ async fetcher(queries: { episodeId: string }[]) { - const data = await $fetch('/episodes', { + const data = (await $fetch('/episodes', { query: { episodeIds: queries.map((q) => q.episodeId).join(','), }, - }); + })) as StandardSchemaV1.InferOutput; return data; }, resolver(items, query: { episodeId: string }) { @@ -55,7 +47,9 @@ export const episodeService: EpisodeService = { return channel; }, async fetchEpisodes() { - const data = await $fetch('/episodes', { query: {} }); + const data = (await $fetch('/episodes', { query: {} })) as StandardSchemaV1.InferOutput< + typeof schema.getEpisodesResponse + >; return data; }, }; diff --git a/workspaces/client/src/features/episode/stores/createEpisodeStoreSlice.ts b/workspaces/client/src/features/episode/stores/createEpisodeStoreSlice.ts index d5d8fef8a..5401d76f6 100644 --- a/workspaces/client/src/features/episode/stores/createEpisodeStoreSlice.ts +++ b/workspaces/client/src/features/episode/stores/createEpisodeStoreSlice.ts @@ -1,6 +1,6 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { produce } from 'immer'; import { episodeService } from '@wsh-2025/client/src/features/episode/services/episodeService'; diff --git a/workspaces/client/src/features/layout/components/AspectRatio.tsx b/workspaces/client/src/features/layout/components/AspectRatio.tsx deleted file mode 100644 index 37b07a5a1..000000000 --- a/workspaces/client/src/features/layout/components/AspectRatio.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { ReactNode, useEffect, useRef } from 'react'; -import { useUpdate } from 'react-use'; - -interface Props { - children: ReactNode; - ratioHeight: number; - ratioWidth: number; -} - -export const AspectRatio = ({ children, ratioHeight, ratioWidth }: Props) => { - const forceUpdate = useUpdate(); - const containerRef = useRef(null); - - useEffect(() => { - const interval = setInterval(function tick() { - forceUpdate(); - }, 1000); - return () => { - clearInterval(interval); - }; - }, []); - - const width = containerRef.current?.getBoundingClientRect().width ?? 0; - const height = (width * ratioHeight) / ratioWidth; - - return ( -
- {children} -
- ); -}; diff --git a/workspaces/client/src/features/layout/components/Hoverable.tsx b/workspaces/client/src/features/layout/components/Hoverable.tsx deleted file mode 100644 index b723d8aee..000000000 --- a/workspaces/client/src/features/layout/components/Hoverable.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import classNames from 'classnames'; -import { Children, cloneElement, ReactElement, Ref, useRef } from 'react'; -import { useMergeRefs } from 'use-callback-ref'; - -import { usePointer } from '@wsh-2025/client/src/features/layout/hooks/usePointer'; - -interface Props { - children: ReactElement<{ className?: string; ref?: Ref }>; - classNames: { - default?: string; - hovered?: string; - }; -} - -export const Hoverable = (props: Props) => { - const child = Children.only(props.children); - const elementRef = useRef(null); - - const mergedRef = useMergeRefs([elementRef, child.props.ref].filter((v) => v != null)); - - const pointer = usePointer(); - const elementRect = elementRef.current?.getBoundingClientRect(); - - const hovered = - elementRect != null && - elementRect.left <= pointer.x && - pointer.x <= elementRect.right && - elementRect.top <= pointer.y && - pointer.y <= elementRect.bottom; - - return cloneElement(child, { - className: classNames( - child.props.className, - 'cursor-pointer', - hovered ? props.classNames.hovered : props.classNames.default, - ), - ref: mergedRef, - }); -}; diff --git a/workspaces/client/src/features/layout/components/Layout.tsx b/workspaces/client/src/features/layout/components/Layout.tsx index 99eadef4b..dd3562563 100644 --- a/workspaces/client/src/features/layout/components/Layout.tsx +++ b/workspaces/client/src/features/layout/components/Layout.tsx @@ -11,15 +11,12 @@ import { useAuthActions } from '@wsh-2025/client/src/features/auth/hooks/useAuth import { useAuthDialogType } from '@wsh-2025/client/src/features/auth/hooks/useAuthDialogType'; import { useAuthUser } from '@wsh-2025/client/src/features/auth/hooks/useAuthUser'; import { Loading } from '@wsh-2025/client/src/features/layout/components/Loading'; -import { useSubscribePointer } from '@wsh-2025/client/src/features/layout/hooks/useSubscribePointer'; interface Props { children: ReactNode; } export const Layout = ({ children }: Props) => { - useSubscribePointer(); - const navigation = useNavigation(); const isLoading = navigation.location != null && (navigation.location.state as { loading?: string } | null)?.['loading'] !== 'none'; @@ -76,7 +73,10 @@ export const Layout = ({ children }: Props) => { onClick={isSignedIn ? authActions.openSignOutDialog : authActions.openSignInDialog} >
{isSignedIn ? 'ログアウト' : 'ログイン'} diff --git a/workspaces/client/src/features/player/components/Player.tsx b/workspaces/client/src/features/player/components/Player.tsx index f1c27e8b9..9d3fa8e58 100644 --- a/workspaces/client/src/features/player/components/Player.tsx +++ b/workspaces/client/src/features/player/components/Player.tsx @@ -2,18 +2,16 @@ import { Ref, useEffect, useRef } from 'react'; import invariant from 'tiny-invariant'; import { assignRef } from 'use-callback-ref'; -import { PlayerType } from '@wsh-2025/client/src/features/player/constants/player_type'; import { PlayerWrapper } from '@wsh-2025/client/src/features/player/interfaces/player_wrapper'; interface Props { className?: string; loop?: boolean; playerRef: Ref; - playerType: PlayerType; playlistUrl: string; } -export const Player = ({ className, loop, playerRef, playerType, playlistUrl }: Props) => { +export const Player = ({ className, loop, playerRef, playlistUrl }: Props) => { const mountRef = useRef(null); useEffect(() => { @@ -27,7 +25,7 @@ export const Player = ({ className, loop, playerRef, playerType, playlistUrl }: if (abortController.signal.aborted) { return; } - player = createPlayer(playerType); + player = createPlayer(); player.load(playlistUrl, { loop: loop ?? false }); mountElement.appendChild(player.videoElement); assignRef(playerRef, player); @@ -41,13 +39,12 @@ export const Player = ({ className, loop, playerRef, playerType, playlistUrl }: } assignRef(playerRef, null); }; - }, [playerType, playlistUrl, loop]); + }, [playlistUrl, loop]); return (
-
diff --git a/workspaces/client/src/features/player/constants/player_type.ts b/workspaces/client/src/features/player/constants/player_type.ts deleted file mode 100644 index 94dbbcb55..000000000 --- a/workspaces/client/src/features/player/constants/player_type.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum PlayerType { - ShakaPlayer = 'shaka-player', - HlsJS = 'hls.js', - VideoJS = 'video-js', -} diff --git a/workspaces/client/src/features/player/interfaces/player_wrapper.ts b/workspaces/client/src/features/player/interfaces/player_wrapper.ts index b6ac58394..4796779e0 100644 --- a/workspaces/client/src/features/player/interfaces/player_wrapper.ts +++ b/workspaces/client/src/features/player/interfaces/player_wrapper.ts @@ -1,5 +1,3 @@ -import { PlayerType } from '@wsh-2025/client/src/features/player/constants/player_type'; - export interface PlayerWrapper { readonly currentTime: number; destory(): void; @@ -9,7 +7,6 @@ export interface PlayerWrapper { pause(): void; readonly paused: boolean; play(): void; - readonly playerType: PlayerType; seekTo(second: number): void; setMuted(muted: boolean): void; readonly videoElement: HTMLVideoElement; diff --git a/workspaces/client/src/features/player/logics/create_player.ts b/workspaces/client/src/features/player/logics/create_player.ts index 823364d27..a36ce0347 100644 --- a/workspaces/client/src/features/player/logics/create_player.ts +++ b/workspaces/client/src/features/player/logics/create_player.ts @@ -1,72 +1,11 @@ -import '@videojs/http-streaming'; import HlsJs from 'hls.js'; -import shaka from 'shaka-player'; -import videojs from 'video.js'; -import { PlayerType } from '@wsh-2025/client/src/features/player/constants/player_type'; import { PlayerWrapper } from '@wsh-2025/client/src/features/player/interfaces/player_wrapper'; -class ShakaPlayerWrapper implements PlayerWrapper { - readonly videoElement = Object.assign(document.createElement('video'), { - autoplay: true, - controls: false, - muted: true, - volume: 0.25, - }); - private _player = new shaka.Player(); - readonly playerType: PlayerType.ShakaPlayer; - - constructor(playerType: PlayerType.ShakaPlayer) { - this.playerType = playerType; - this._player.configure({ - streaming: { - bufferingGoal: 50, - }, - }); - } - - get currentTime(): number { - const currentTime = this.videoElement.currentTime; - return Number.isNaN(currentTime) ? 0 : currentTime; - } - get paused(): boolean { - return this.videoElement.paused; - } - get duration(): number { - const duration = this.videoElement.duration; - return Number.isNaN(duration) ? 0 : duration; - } - get muted(): boolean { - return this.videoElement.muted; - } - - load(playlistUrl: string, options: { loop: boolean }): void { - void (async () => { - await this._player.attach(this.videoElement); - this.videoElement.loop = options.loop; - await this._player.load(playlistUrl); - })(); - } - play(): void { - void this.videoElement.play(); - } - pause(): void { - this.videoElement.pause(); - } - seekTo(second: number): void { - this.videoElement.currentTime = second; - } - setMuted(muted: boolean): void { - this.videoElement.muted = muted; - } - destory(): void { - void this._player.destroy(); - } -} - class HlsJSPlayerWrapper implements PlayerWrapper { readonly videoElement = Object.assign(document.createElement('video'), { autoplay: true, + className: 'aspect-video', controls: false, muted: true, volume: 0.25, @@ -75,11 +14,6 @@ class HlsJSPlayerWrapper implements PlayerWrapper { enableWorker: false, maxBufferLength: 50, }); - readonly playerType: PlayerType.HlsJS; - - constructor(playerType: PlayerType.HlsJS) { - this.playerType = playerType; - } get currentTime(): number { const currentTime = this.videoElement.currentTime; @@ -118,79 +52,6 @@ class HlsJSPlayerWrapper implements PlayerWrapper { } } -interface VhsConfig { - GOAL_BUFFER_LENGTH: number; - MAX_GOAL_BUFFER_LENGTH: number; -} - -class VideoJSPlayerWrapper implements PlayerWrapper { - readonly videoElement = Object.assign(document.createElement('video'), { - autoplay: true, - controls: false, - muted: true, - volume: 0.25, - }); - private _player = videojs(this.videoElement); - readonly playerType: PlayerType.VideoJS; - - constructor(playerType: PlayerType.VideoJS) { - const vhsConfig = (videojs as unknown as { Vhs: VhsConfig }).Vhs; - vhsConfig.GOAL_BUFFER_LENGTH = 50; - vhsConfig.MAX_GOAL_BUFFER_LENGTH = 50; - this.playerType = playerType; - } - - get currentTime(): number { - return this._player.currentTime() ?? 0; - } - get paused(): boolean { - return this._player.paused(); - } - get duration(): number { - return this._player.duration() ?? 0; - } - get muted(): boolean { - return this._player.muted() ?? true; - } - - load(playlistUrl: string, options: { loop: boolean }): void { - this.videoElement.loop = options.loop; - this._player.src({ - src: playlistUrl, - type: 'application/x-mpegURL', - }); - } - play(): void { - void this.videoElement.play(); - } - pause(): void { - this.videoElement.pause(); - } - seekTo(second: number): void { - this.videoElement.currentTime = second; - } - setMuted(muted: boolean): void { - this._player.muted(muted); - } - destory(): void { - this._player.dispose(); - } -} - -export const createPlayer = (playerType: PlayerType): PlayerWrapper => { - switch (playerType) { - case PlayerType.ShakaPlayer: { - return new ShakaPlayerWrapper(playerType); - } - case PlayerType.HlsJS: { - return new HlsJSPlayerWrapper(playerType); - } - case PlayerType.VideoJS: { - return new VideoJSPlayerWrapper(playerType); - } - default: { - playerType satisfies never; - throw new Error('Invalid player type.'); - } - } +export const createPlayer = (): PlayerWrapper => { + return new HlsJSPlayerWrapper(); }; diff --git a/workspaces/client/src/features/program/services/programService.ts b/workspaces/client/src/features/program/services/programService.ts index dc17a25c0..e664cb278 100644 --- a/workspaces/client/src/features/program/services/programService.ts +++ b/workspaces/client/src/features/program/services/programService.ts @@ -1,6 +1,7 @@ -import { createFetch, createSchema } from '@better-fetch/fetch'; +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +import { createFetch } from '@better-fetch/fetch'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import * as batshit from '@yornaath/batshit'; import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin'; @@ -8,26 +9,16 @@ import { schedulePlugin } from '@wsh-2025/client/src/features/requests/scheduleP const $fetch = createFetch({ baseURL: process.env['API_BASE_URL'] ?? '/api', plugins: [schedulePlugin], - schema: createSchema({ - '/programs': { - output: schema.getProgramsResponse, - query: schema.getProgramsRequestQuery, - }, - '/programs/:episodeId': { - output: schema.getProgramByIdResponse, - params: schema.getProgramByIdRequestParams, - }, - }), throw: true, }); const batcher = batshit.create({ async fetcher(queries: { programId: string }[]) { - const data = await $fetch('/programs', { + const data = (await $fetch('/programs', { query: { programIds: queries.map((q) => q.programId).join(','), }, - }); + })) as StandardSchemaV1.InferOutput; return data; }, resolver(items, query: { programId: string }) { @@ -56,7 +47,9 @@ export const programService: ProgramService = { return channel; }, async fetchPrograms() { - const data = await $fetch('/programs', { query: {} }); + const data = (await $fetch('/programs', { query: {} })) as StandardSchemaV1.InferOutput< + typeof schema.getProgramsResponse + >; return data; }, }; diff --git a/workspaces/client/src/features/program/stores/createProgramStoreSlice.ts b/workspaces/client/src/features/program/stores/createProgramStoreSlice.ts index 46d1a935a..e34f18d44 100644 --- a/workspaces/client/src/features/program/stores/createProgramStoreSlice.ts +++ b/workspaces/client/src/features/program/stores/createProgramStoreSlice.ts @@ -1,6 +1,6 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { produce } from 'immer'; import { programService } from '@wsh-2025/client/src/features/program/services/programService'; diff --git a/workspaces/client/src/features/recommended/components/CarouselSection.tsx b/workspaces/client/src/features/recommended/components/CarouselSection.tsx index e81aa410e..7e92d88d0 100644 --- a/workspaces/client/src/features/recommended/components/CarouselSection.tsx +++ b/workspaces/client/src/features/recommended/components/CarouselSection.tsx @@ -1,22 +1,18 @@ import { ElementScrollRestoration } from '@epic-web/restore-scroll'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { ArrayValues } from 'type-fest'; -import { useMergeRefs } from 'use-callback-ref'; import { EpisodeItem } from '@wsh-2025/client/src/features/recommended/components/EpisodeItem'; import { SeriesItem } from '@wsh-2025/client/src/features/recommended/components/SeriesItem'; import { useCarouselItemWidth } from '@wsh-2025/client/src/features/recommended/hooks/useCarouselItemWidth'; -import { useScrollSnap } from '@wsh-2025/client/src/features/recommended/hooks/useScrollSnap'; interface Props { module: ArrayValues>; } export const CarouselSection = ({ module }: Props) => { - const containerRefForScrollSnap = useScrollSnap({ scrollPadding: 24 }); const { ref: containerRefForItemWidth, width: itemWidth } = useCarouselItemWidth(); - const mergedRef = useMergeRefs([containerRefForItemWidth, containerRefForScrollSnap]); return ( <> @@ -24,12 +20,12 @@ export const CarouselSection = ({ module }: Props) => {

{module.title}

{module.items.map((item) => ( -
+
{item.series != null ? : null} {item.episode != null ? : null}
diff --git a/workspaces/client/src/features/recommended/components/EpisodeItem.tsx b/workspaces/client/src/features/recommended/components/EpisodeItem.tsx index 74b08745c..941da5f70 100644 --- a/workspaces/client/src/features/recommended/components/EpisodeItem.tsx +++ b/workspaces/client/src/features/recommended/components/EpisodeItem.tsx @@ -1,9 +1,6 @@ -import Ellipsis from 'react-ellipsis-component'; import { Flipped } from 'react-flip-toolkit'; import { NavLink } from 'react-router'; -import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; - interface Props { episode: { id: string; @@ -18,34 +15,38 @@ interface Props { export const EpisodeItem = ({ episode }: Props) => { return ( - - - {({ isTransitioning }) => { - return ( - <> - -
- - - {episode.premium ? ( - - プレミアム - - ) : null} -
-
-
-
- -
-
- -
+ + {({ isTransitioning }) => { + return ( + <> + +
+ + + {episode.premium ? ( + + プレミアム + + ) : null}
- - ); - }} -
- + +
+
{episode.title}
+
{episode.series.title}
+
+ + ); + }} + ); }; diff --git a/workspaces/client/src/features/recommended/components/JumbotronSection.tsx b/workspaces/client/src/features/recommended/components/JumbotronSection.tsx index 638c9cfd6..40282b0b6 100644 --- a/workspaces/client/src/features/recommended/components/JumbotronSection.tsx +++ b/workspaces/client/src/features/recommended/components/JumbotronSection.tsx @@ -1,18 +1,14 @@ import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { useRef } from 'react'; -import Ellipsis from 'react-ellipsis-component'; import { Flipped } from 'react-flip-toolkit'; import { NavLink } from 'react-router'; import invariant from 'tiny-invariant'; import { ArrayValues } from 'type-fest'; import { Player } from '../../player/components/Player'; -import { PlayerType } from '../../player/constants/player_type'; import { PlayerWrapper } from '../../player/interfaces/player_wrapper'; -import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; - interface Props { module: ArrayValues>; } @@ -24,39 +20,36 @@ export const JumbotronSection = ({ module }: Props) => { invariant(episode); return ( - - - {({ isTransitioning }) => { - return ( - <> -
-
- -
-
- -
+ + {({ isTransitioning }) => { + return ( + <> +
+
+ {episode.title} +
+
+ {episode.description}
+
- -
- -
-
- - ); - }} -
- + +
+ +
+
+ + ); + }} + ); }; diff --git a/workspaces/client/src/features/recommended/components/RecommendedSection.tsx b/workspaces/client/src/features/recommended/components/RecommendedSection.tsx index d3e287ef0..38a345061 100644 --- a/workspaces/client/src/features/recommended/components/RecommendedSection.tsx +++ b/workspaces/client/src/features/recommended/components/RecommendedSection.tsx @@ -1,5 +1,5 @@ import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { ArrayValues } from 'type-fest'; import { CarouselSection } from '@wsh-2025/client/src/features/recommended/components/CarouselSection'; diff --git a/workspaces/client/src/features/recommended/components/SeriesItem.tsx b/workspaces/client/src/features/recommended/components/SeriesItem.tsx index 2477b7a97..c265e3da0 100644 --- a/workspaces/client/src/features/recommended/components/SeriesItem.tsx +++ b/workspaces/client/src/features/recommended/components/SeriesItem.tsx @@ -1,9 +1,6 @@ -import Ellipsis from 'react-ellipsis-component'; import { Flipped } from 'react-flip-toolkit'; import { NavLink } from 'react-router'; -import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; - interface Props { series: { id: string; @@ -14,25 +11,31 @@ interface Props { export const SeriesItem = ({ series }: Props) => { return ( - - - {({ isTransitioning }) => { - return ( - <> -
- - - -
-
-
- -
-
- - ); - }} -
-
+ + {({ isTransitioning }) => { + return ( + <> +
+ + + +
+
+
{series.title}
+
+ + ); + }} +
); }; diff --git a/workspaces/client/src/features/recommended/hooks/useScrollSnap.ts b/workspaces/client/src/features/recommended/hooks/useScrollSnap.ts index e6cb168e7..204c7cd43 100644 --- a/workspaces/client/src/features/recommended/hooks/useScrollSnap.ts +++ b/workspaces/client/src/features/recommended/hooks/useScrollSnap.ts @@ -11,48 +11,67 @@ export function useScrollSnap({ scrollPadding }: { scrollPadding: number }) { } const handleScroll = () => { + // スクロール中であれば if (isScrolling.current) { + // 何もしない return; } + // スクロール中でなければスクロール中のフラグを立てる isScrolling.current = true; }; const handleScrollend = () => { + // スクロール中でなければ if (!isScrolling.current) { + // 何もしない return; } + // スクロール中であればスクロール中のフラグを外す isScrolling.current = false; }; let timer: ReturnType | null = null; let interval = setInterval(() => { + // スクロール中でなければ if (!containerRef.current) { + // 何もしない return; } + // 子要素を全て取得する const childElements = Array.from(containerRef.current.children) as HTMLElement[]; + // 子要素の位置を取得する const childScrollPositions = childElements.map((element) => element.offsetLeft); + // 親要素の位置を取得する const scrollPosition = containerRef.current.scrollLeft; + // 親要素と最も近い子要素の添字を取得する const childIndex = childScrollPositions.reduce((prev, curr, index) => { return Math.abs(curr - scrollPosition) < Math.abs((childScrollPositions[prev] ?? 0) - scrollPosition) ? index : prev; }, 0); + // スクロール中であれば if (isScrolling.current) { + // 何もしない return; } + // スナップ中であれば if (isSnapping.current) { + // 何もしない return; } + // スナップ中のフラグを立てる isSnapping.current = true; + // 親要素に最も近い子要素の位置に揃える containerRef.current.scrollTo({ behavior: 'smooth', left: (childScrollPositions[childIndex] ?? 0) - scrollPadding, }); + // 1秒後にスナップ中のフラグを下げる timer = setTimeout(() => { isSnapping.current = false; }, 1000); diff --git a/workspaces/client/src/features/recommended/services/recommendedService.ts b/workspaces/client/src/features/recommended/services/recommendedService.ts index 494ad911f..2e2a8c7e4 100644 --- a/workspaces/client/src/features/recommended/services/recommendedService.ts +++ b/workspaces/client/src/features/recommended/services/recommendedService.ts @@ -1,17 +1,13 @@ -import { createFetch, createSchema } from '@better-fetch/fetch'; +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +import { createFetch } from '@better-fetch/fetch'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin'; const $fetch = createFetch({ baseURL: process.env['API_BASE_URL'] ?? '/api', plugins: [schedulePlugin], - schema: createSchema({ - '/recommended/:referenceId': { - output: schema.getRecommendedModulesResponse, - }, - }), throw: true, }); @@ -23,9 +19,9 @@ interface RecommendedService { export const recommendedService: RecommendedService = { async fetchRecommendedModulesByReferenceId({ referenceId }) { - const data = await $fetch('/recommended/:referenceId', { + const data = (await $fetch('/recommended/:referenceId', { params: { referenceId }, - }); + })) as StandardSchemaV1.InferOutput; return data; }, }; diff --git a/workspaces/client/src/features/recommended/stores/createRecomendedStoreSlice.ts b/workspaces/client/src/features/recommended/stores/createRecomendedStoreSlice.ts index aa2c858fc..3d6f3932d 100644 --- a/workspaces/client/src/features/recommended/stores/createRecomendedStoreSlice.ts +++ b/workspaces/client/src/features/recommended/stores/createRecomendedStoreSlice.ts @@ -1,6 +1,6 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { produce } from 'immer'; import { ArrayValues } from 'type-fest'; diff --git a/workspaces/client/src/features/series/components/SeriesEpisodeItem.tsx b/workspaces/client/src/features/series/components/SeriesEpisodeItem.tsx new file mode 100644 index 000000000..bc1994f15 --- /dev/null +++ b/workspaces/client/src/features/series/components/SeriesEpisodeItem.tsx @@ -0,0 +1,52 @@ +import { Flipped } from 'react-flip-toolkit'; +import { NavLink } from 'react-router'; + +interface Props { + episode: { + description: string; + id: string; + premium: boolean; + thumbnailUrl: string; + title: string; + }; + selected: boolean; +} + +export const SeriesEpisodeItem = ({ episode, selected }: Props) => { + return ( + + {({ isTransitioning }) => { + return ( + <> + +
+ + + {episode.premium ? ( + + プレミアム + + ) : null} +
+
+ +
+
{episode.title}
+
{episode.description}
+
+ + ); + }} +
+ ); +}; diff --git a/workspaces/client/src/features/series/components/SeriesEpisodeList.tsx b/workspaces/client/src/features/series/components/SeriesEpisodeList.tsx index 4e258eecb..8933d11db 100644 --- a/workspaces/client/src/features/series/components/SeriesEpisodeList.tsx +++ b/workspaces/client/src/features/series/components/SeriesEpisodeList.tsx @@ -1,4 +1,4 @@ -import { SeriesEpisodeItem } from '@wsh-2025/client/src/features/series/components/SeriesEposideItem'; +import { SeriesEpisodeItem } from '@wsh-2025/client/src/features/series/components/SeriesEpisodeItem'; interface Props { episodes: { diff --git a/workspaces/client/src/features/series/components/SeriesEposideItem.tsx b/workspaces/client/src/features/series/components/SeriesEposideItem.tsx deleted file mode 100644 index 0a0067d95..000000000 --- a/workspaces/client/src/features/series/components/SeriesEposideItem.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import Ellipsis from 'react-ellipsis-component'; -import { Flipped } from 'react-flip-toolkit'; -import { NavLink } from 'react-router'; - -import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; - -interface Props { - episode: { - description: string; - id: string; - premium: boolean; - thumbnailUrl: string; - title: string; - }; - selected: boolean; -} - -export const SeriesEpisodeItem = ({ episode, selected }: Props) => { - return ( - - - {({ isTransitioning }) => { - return ( - <> - -
- - - {episode.premium ? ( - - プレミアム - - ) : null} -
-
- -
-
- -
-
- -
-
- - ); - }} -
-
- ); -}; diff --git a/workspaces/client/src/features/series/services/seriesService.ts b/workspaces/client/src/features/series/services/seriesService.ts index 2c27f2e1a..6f7d2cc2e 100644 --- a/workspaces/client/src/features/series/services/seriesService.ts +++ b/workspaces/client/src/features/series/services/seriesService.ts @@ -1,6 +1,7 @@ -import { createFetch, createSchema } from '@better-fetch/fetch'; +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +import { createFetch } from '@better-fetch/fetch'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import * as batshit from '@yornaath/batshit'; import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin'; @@ -8,25 +9,16 @@ import { schedulePlugin } from '@wsh-2025/client/src/features/requests/scheduleP const $fetch = createFetch({ baseURL: process.env['API_BASE_URL'] ?? '/api', plugins: [schedulePlugin], - schema: createSchema({ - '/series': { - output: schema.getSeriesResponse, - query: schema.getSeriesRequestQuery, - }, - '/series/:seriesId': { - output: schema.getSeriesByIdResponse, - }, - }), throw: true, }); const batcher = batshit.create({ async fetcher(queries: { seriesId: string }[]) { - const data = await $fetch('/series', { + const data = (await $fetch('/series', { query: { seriesIds: queries.map((q) => q.seriesId).join(','), }, - }); + })) as StandardSchemaV1.InferOutput; return data; }, resolver(items, query: { seriesId: string }) { @@ -51,7 +43,9 @@ interface SeriesService { export const seriesService: SeriesService = { async fetchSeries() { - const data = await $fetch('/series', { query: {} }); + const data = (await $fetch('/series', { query: {} })) as StandardSchemaV1.InferOutput< + typeof schema.getSeriesResponse + >; return data; }, async fetchSeriesById({ seriesId }) { diff --git a/workspaces/client/src/features/series/stores/createSeriesStoreSlice.ts b/workspaces/client/src/features/series/stores/createSeriesStoreSlice.ts index 9385fb5a5..a10939796 100644 --- a/workspaces/client/src/features/series/stores/createSeriesStoreSlice.ts +++ b/workspaces/client/src/features/series/stores/createSeriesStoreSlice.ts @@ -1,6 +1,6 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { produce } from 'immer'; import { seriesService } from '@wsh-2025/client/src/features/series/services/seriesService'; diff --git a/workspaces/client/src/features/timetable/hooks/useTimetable.ts b/workspaces/client/src/features/timetable/hooks/useTimetable.ts index dff10c5cd..5020a3feb 100644 --- a/workspaces/client/src/features/timetable/hooks/useTimetable.ts +++ b/workspaces/client/src/features/timetable/hooks/useTimetable.ts @@ -1,4 +1,4 @@ -import { DateTime } from 'luxon'; +import dayjs from 'dayjs'; import { ArrayValues } from 'type-fest'; import { useStore } from '@wsh-2025/client/src/app/StoreContext'; @@ -23,7 +23,7 @@ export function useTimetable() { } record[channel.id] = filteredPrograms.sort((a, b) => { - return DateTime.fromISO(a.startAt).toMillis() - DateTime.fromISO(b.startAt).toMillis(); + return dayjs(a.startAt).valueOf() - dayjs(b.startAt).valueOf(); }); } diff --git a/workspaces/client/src/features/timetable/services/timetableService.ts b/workspaces/client/src/features/timetable/services/timetableService.ts index e7137d6b0..a1e6a77b8 100644 --- a/workspaces/client/src/features/timetable/services/timetableService.ts +++ b/workspaces/client/src/features/timetable/services/timetableService.ts @@ -1,18 +1,13 @@ -import { createFetch, createSchema } from '@better-fetch/fetch'; +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +import { createFetch } from '@better-fetch/fetch'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin'; const $fetch = createFetch({ baseURL: process.env['API_BASE_URL'] ?? '/api', plugins: [schedulePlugin], - schema: createSchema({ - '/timetable': { - output: schema.getTimetableResponse, - query: schema.getTimetableRequestQuery, - }, - }), throw: true, }); @@ -24,9 +19,9 @@ interface TimetableService { export const timetableService: TimetableService = { async fetchTimetable({ since, until }) { - const data = await $fetch('/timetable', { + const data = (await $fetch('/timetable', { query: { since, until }, - }); + })) as StandardSchemaV1.InferOutput; return data; }, }; diff --git a/workspaces/client/src/features/timetable/stores/createTimetableStoreSlice.ts b/workspaces/client/src/features/timetable/stores/createTimetableStoreSlice.ts index 7413bd96a..cdef2e0dc 100644 --- a/workspaces/client/src/features/timetable/stores/createTimetableStoreSlice.ts +++ b/workspaces/client/src/features/timetable/stores/createTimetableStoreSlice.ts @@ -1,6 +1,6 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { produce } from 'immer'; import { ArrayValues } from 'type-fest'; diff --git a/workspaces/client/src/main.tsx b/workspaces/client/src/main.tsx index 601b7a6a5..5d18a8777 100644 --- a/workspaces/client/src/main.tsx +++ b/workspaces/client/src/main.tsx @@ -1,5 +1,4 @@ -import '@wsh-2025/client/src/setups/polyfills'; -import '@wsh-2025/client/src/setups/luxon'; +import '@wsh-2025/client/src/setups/dayjs'; import '@wsh-2025/client/src/setups/unocss'; import { StrictMode } from 'react'; @@ -16,7 +15,7 @@ declare global { } function main() { - const store = createStore({}); + const store = createStore(); const router = createBrowserRouter(createRoutes(store), {}); hydrateRoot( diff --git a/workspaces/client/src/pages/episode/components/EpisodePage.tsx b/workspaces/client/src/pages/episode/components/EpisodePage.tsx index 075eacc48..001f67847 100644 --- a/workspaces/client/src/pages/episode/components/EpisodePage.tsx +++ b/workspaces/client/src/pages/episode/components/EpisodePage.tsx @@ -1,18 +1,13 @@ import { Suspense } from 'react'; -import Ellipsis from 'react-ellipsis-component'; import { Flipped } from 'react-flip-toolkit'; -import { Params, useParams } from 'react-router'; +import { Params, useLoaderData } from 'react-router'; import invariant from 'tiny-invariant'; import { createStore } from '@wsh-2025/client/src/app/createStore'; import { useAuthActions } from '@wsh-2025/client/src/features/auth/hooks/useAuthActions'; import { useAuthUser } from '@wsh-2025/client/src/features/auth/hooks/useAuthUser'; -import { useEpisodeById } from '@wsh-2025/client/src/features/episode/hooks/useEpisodeById'; -import { AspectRatio } from '@wsh-2025/client/src/features/layout/components/AspectRatio'; import { Player } from '@wsh-2025/client/src/features/player/components/Player'; -import { PlayerType } from '@wsh-2025/client/src/features/player/constants/player_type'; import { RecommendedSection } from '@wsh-2025/client/src/features/recommended/components/RecommendedSection'; -import { useRecommended } from '@wsh-2025/client/src/features/recommended/hooks/useRecommended'; import { SeriesEpisodeList } from '@wsh-2025/client/src/features/series/components/SeriesEpisodeList'; import { PlayerController } from '@wsh-2025/client/src/pages/episode/components/PlayerController'; import { usePlayerRef } from '@wsh-2025/client/src/pages/episode/hooks/usePlayerRef'; @@ -27,16 +22,12 @@ export const prefetch = async (store: ReturnType, { episodeI }; export const EpisodePage = () => { - const authActions = useAuthActions(); - const user = useAuthUser(); - - const { episodeId } = useParams(); - invariant(episodeId); - - const episode = useEpisodeById({ episodeId }); + type PrefetchReturnType = ReturnType; + const { episode, modules } = useLoaderData>(); invariant(episode); - const modules = useRecommended({ referenceId: episodeId }); + const authActions = useAuthActions(); + const user = useAuthUser(); const playerRef = usePlayerRef(); @@ -51,7 +42,13 @@ export const EpisodePage = () => {
{isSignInRequired ? (
- +

@@ -69,24 +66,25 @@ export const EpisodePage = () => { ) : ( +

- +
} >
@@ -100,12 +98,8 @@ export const EpisodePage = () => {
-
- -
-

- -

+
{episode.series.title}
+

{episode.title}

{episode.premium ? (
@@ -113,9 +107,7 @@ export const EpisodePage = () => {
) : null} -
- -
+
{episode.description}
{modules[0] != null ? ( diff --git a/workspaces/client/src/pages/episode/components/PlayerController.tsx b/workspaces/client/src/pages/episode/components/PlayerController.tsx index f090a17a9..f55d61174 100644 --- a/workspaces/client/src/pages/episode/components/PlayerController.tsx +++ b/workspaces/client/src/pages/episode/components/PlayerController.tsx @@ -1,10 +1,10 @@ import * as Slider from '@radix-ui/react-slider'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; -import { Duration } from 'luxon'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; +import classNames from 'classnames'; +import dayjs from 'dayjs'; import invariant from 'tiny-invariant'; -import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; import { SeekThumbnail } from '@wsh-2025/client/src/pages/episode/components/SeekThumbnail'; import { useCurrentTime } from '@wsh-2025/client/src/pages/episode/hooks/useCurrentTime'; import { useDuration } from '@wsh-2025/client/src/pages/episode/hooks/useDuration'; @@ -52,44 +52,46 @@ export const PlayerController = ({ episode }: Props) => {
- - - + - {Duration.fromObject({ seconds: currentTime }).toFormat('mm:ss')} + {dayjs.duration(currentTime, 'seconds').format('mm:ss')} {' / '} - {Duration.fromObject({ seconds: duration }).toFormat('mm:ss')} + {dayjs.duration(duration, 'seconds').format('mm:ss')}
- - - +
diff --git a/workspaces/client/src/pages/episode/components/SeekThumbnail.tsx b/workspaces/client/src/pages/episode/components/SeekThumbnail.tsx index b706a379b..e3878793c 100644 --- a/workspaces/client/src/pages/episode/components/SeekThumbnail.tsx +++ b/workspaces/client/src/pages/episode/components/SeekThumbnail.tsx @@ -1,8 +1,7 @@ import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; -import { useRef } from 'react'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; +import { useEffect, useRef, useState } from 'react'; -import { usePointer } from '@wsh-2025/client/src/features/layout/hooks/usePointer'; import { useDuration } from '@wsh-2025/client/src/pages/episode/hooks/useDuration'; import { useSeekThumbnail } from '@wsh-2025/client/src/pages/episode/hooks/useSeekThumbnail'; @@ -14,14 +13,26 @@ interface Props { export const SeekThumbnail = ({ episode }: Props) => { const ref = useRef(null); - const seekThumbnail = useSeekThumbnail({ episode }); - const pointer = usePointer(); + const seekThumbnailUrl = useSeekThumbnail({ episode }); const duration = useDuration(); + const [pointer, setPointer] = useState({ x: 0, y: 0 }); + + useEffect(() => { + const handlePointerMove = (ev: MouseEvent) => { + setPointer({ x: ev.clientX, y: ev.clientY }); + }; + window.addEventListener('pointermove', handlePointerMove); + + return () => { + window.removeEventListener('pointermove', handlePointerMove); + }; + }, [ref]); + const elementRect = ref.current?.parentElement?.getBoundingClientRect() ?? { left: 0, width: 0 }; const relativeX = pointer.x - elementRect.left; - const percentage = Math.max(0, Math.min(relativeX / elementRect.width, 1)); + const percentage = Math.max(0, Math.min(0 < elementRect.width ? relativeX / elementRect.width : 0, 1)); const pointedTime = duration * percentage; // サムネイルが画面からはみ出ないようにサムネイル中央を基準として left を計算する @@ -31,8 +42,9 @@ export const SeekThumbnail = ({ episode }: Props) => { return (
; } -async function getSeekThumbnail({ episode }: Params) { - // HLS のプレイリストを取得 - const playlistUrl = `/streams/episode/${episode.id}/playlist.m3u8`; - const parser = new Parser(); - parser.push(await fetch(playlistUrl).then((res) => res.text())); - parser.end(); - - // FFmpeg の初期化 - const ffmpeg = new FFmpeg(); - await ffmpeg.load({ - coreURL: await import('@ffmpeg/core?arraybuffer').then(({ default: b }) => { - return URL.createObjectURL(new Blob([b], { type: 'text/javascript' })); - }), - wasmURL: await import('@ffmpeg/core/wasm?arraybuffer').then(({ default: b }) => { - return URL.createObjectURL(new Blob([b], { type: 'application/wasm' })); - }), - }); - - // 動画のセグメントファイルを取得 - const segmentFiles = await Promise.all( - parser.manifest.segments.map((s) => { - return fetch(s.uri).then(async (res) => { - const binary = await res.arrayBuffer(); - return { binary, id: Math.random().toString(36).slice(2) }; - }); - }), - ); - // FFmpeg にセグメントファイルを追加 - for (const file of segmentFiles) { - await ffmpeg.writeFile(file.id, new Uint8Array(file.binary)); - } - - // セグメントファイルをひとつの mp4 動画に結合 - await ffmpeg.exec( - [ - ['-i', `concat:${segmentFiles.map((f) => f.id).join('|')}`], - ['-c:v', 'copy'], - ['-map', '0:v:0'], - ['-f', 'mp4'], - 'concat.mp4', - ].flat(), - ); - - // fps=30 とみなして、30 フレームごと(1 秒ごと)にサムネイルを生成 - await ffmpeg.exec( - [ - ['-i', 'concat.mp4'], - ['-vf', "fps=30,select='not(mod(n\\,30))',scale=160:90,tile=250x1"], - ['-frames:v', '1'], - 'preview.jpg', - ].flat(), - ); - - const output = await ffmpeg.readFile('preview.jpg'); - ffmpeg.terminate(); - - return URL.createObjectURL(new Blob([output], { type: 'image/jpeg' })); -} - -const weakMap = new WeakMap>(); - export const useSeekThumbnail = ({ episode }: Params): string => { - const promise = weakMap.get(episode) ?? getSeekThumbnail({ episode }); - weakMap.set(episode, promise); - return use(promise); + return `/public/images/thumbnails/${episode.streamId}/preview.jpg`; }; diff --git a/workspaces/client/src/pages/not_found/components/NotFoundPage.tsx b/workspaces/client/src/pages/not_found/components/NotFoundPage.tsx index 66c861769..c446b68d5 100644 --- a/workspaces/client/src/pages/not_found/components/NotFoundPage.tsx +++ b/workspaces/client/src/pages/not_found/components/NotFoundPage.tsx @@ -21,7 +21,10 @@ export const NotFoundPage = () => {

ページが見つかりませんでした

あなたが見ようとしたページは、残念ながら見つけられませんでした。

- +
{module != null ? : null}
diff --git a/workspaces/client/src/pages/program/components/PlayerController.tsx b/workspaces/client/src/pages/program/components/PlayerController.tsx index 6a1c7fef0..60e0bf127 100644 --- a/workspaces/client/src/pages/program/components/PlayerController.tsx +++ b/workspaces/client/src/pages/program/components/PlayerController.tsx @@ -1,4 +1,5 @@ -import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable'; +import classNames from 'classnames'; + import { useMuted } from '@wsh-2025/client/src/pages/program/hooks/useMuted'; export const PlayerController = () => { @@ -16,20 +17,21 @@ export const PlayerController = () => {
- - - +
diff --git a/workspaces/client/src/pages/program/components/ProgramPage.tsx b/workspaces/client/src/pages/program/components/ProgramPage.tsx index d13dc9426..904cc2e06 100644 --- a/workspaces/client/src/pages/program/components/ProgramPage.tsx +++ b/workspaces/client/src/pages/program/components/ProgramPage.tsx @@ -1,17 +1,13 @@ -import { DateTime } from 'luxon'; +import dayjs from 'dayjs'; import { useEffect, useRef } from 'react'; -import Ellipsis from 'react-ellipsis-component'; import { Flipped } from 'react-flip-toolkit'; -import { Link, Params, useNavigate, useParams } from 'react-router'; +import { Link, Params, useLoaderData, useNavigate } from 'react-router'; import { useUpdate } from 'react-use'; import invariant from 'tiny-invariant'; import { createStore } from '@wsh-2025/client/src/app/createStore'; import { Player } from '@wsh-2025/client/src/features/player/components/Player'; -import { PlayerType } from '@wsh-2025/client/src/features/player/constants/player_type'; -import { useProgramById } from '@wsh-2025/client/src/features/program/hooks/useProgramById'; import { RecommendedSection } from '@wsh-2025/client/src/features/recommended/components/RecommendedSection'; -import { useRecommended } from '@wsh-2025/client/src/features/recommended/hooks/useRecommended'; import { SeriesEpisodeList } from '@wsh-2025/client/src/features/series/components/SeriesEpisodeList'; import { useTimetable } from '@wsh-2025/client/src/features/timetable/hooks/useTimetable'; import { PlayerController } from '@wsh-2025/client/src/pages/program/components/PlayerController'; @@ -20,9 +16,9 @@ import { usePlayerRef } from '@wsh-2025/client/src/pages/program/hooks/usePlayer export const prefetch = async (store: ReturnType, { programId }: Params) => { invariant(programId); - const now = DateTime.now(); - const since = now.startOf('day').toISO(); - const until = now.endOf('day').toISO(); + const now = dayjs(); + const since = now.startOf('day').toISOString(); + const until = now.endOf('day').toISOString(); const program = await store.getState().features.program.fetchProgramById({ programId }); const channels = await store.getState().features.channel.fetchChannels(); @@ -34,25 +30,21 @@ export const prefetch = async (store: ReturnType, { programI }; export const ProgramPage = () => { - const { programId } = useParams(); - invariant(programId); - - const program = useProgramById({ programId }); + type PrefetchReturnType = ReturnType; + const { modules, program } = useLoaderData>(); invariant(program); const timetable = useTimetable(); const nextProgram = timetable[program.channel.id]?.find((p) => { - return DateTime.fromISO(program.endAt).equals(DateTime.fromISO(p.startAt)); + return dayjs(program.endAt).isSame(dayjs(p.startAt)); }); - const modules = useRecommended({ referenceId: programId }); - const playerRef = usePlayerRef(); const forceUpdate = useUpdate(); const navigate = useNavigate(); - const isArchivedRef = useRef(DateTime.fromISO(program.endAt) <= DateTime.now()); - const isBroadcastStarted = DateTime.fromISO(program.startAt) <= DateTime.now(); + const isArchivedRef = useRef(dayjs(program.endAt).isBefore(dayjs())); + const isBroadcastStarted = dayjs(program.startAt).isBefore(dayjs()); useEffect(() => { if (isArchivedRef.current) { return; @@ -71,7 +63,7 @@ export const ProgramPage = () => { // 放送中に次の番組が始まったら、画面をそのままにしつつ、情報を次の番組にする let timeout = setTimeout(function tick() { - if (DateTime.now() < DateTime.fromISO(program.endAt)) { + if (dayjs().isBefore(dayjs(program.endAt))) { timeout = setTimeout(tick, 250); return; } @@ -101,7 +93,13 @@ export const ProgramPage = () => {
{isArchivedRef.current ? (
- +

この番組は放送が終了しました

@@ -118,7 +116,6 @@ export const ProgramPage = () => {
@@ -127,11 +124,17 @@ export const ProgramPage = () => {
) : (
- +

- この番組は {DateTime.fromISO(program.startAt).toFormat('L月d日 H:mm')} に放送予定です + この番組は {dayjs(program.startAt).format('M月D日 H:mm')} に放送予定です

@@ -140,20 +143,14 @@ export const ProgramPage = () => {
-
- -
-

- -

+
{program.episode.series.title}
+

{program.title}

- {DateTime.fromISO(program.startAt).toFormat('L月d日 H:mm')} + {dayjs(program.startAt).format('M月D日 H:mm')} {' 〜 '} - {DateTime.fromISO(program.endAt).toFormat('L月d日 H:mm')} -
-
- + {dayjs(program.endAt).format('M月D日 H:mm')}
+
{program.description}
{modules[0] != null ? ( diff --git a/workspaces/client/src/pages/series/components/SeriesPage.tsx b/workspaces/client/src/pages/series/components/SeriesPage.tsx index abf35aee5..162a104e6 100644 --- a/workspaces/client/src/pages/series/components/SeriesPage.tsx +++ b/workspaces/client/src/pages/series/components/SeriesPage.tsx @@ -1,13 +1,10 @@ -import Ellipsis from 'react-ellipsis-component'; import { Flipped } from 'react-flip-toolkit'; -import { Params, useParams } from 'react-router'; +import { Params, useLoaderData } from 'react-router'; import invariant from 'tiny-invariant'; import { createStore } from '@wsh-2025/client/src/app/createStore'; import { RecommendedSection } from '@wsh-2025/client/src/features/recommended/components/RecommendedSection'; -import { useRecommended } from '@wsh-2025/client/src/features/recommended/hooks/useRecommended'; import { SeriesEpisodeList } from '@wsh-2025/client/src/features/series/components/SeriesEpisodeList'; -import { useSeriesById } from '@wsh-2025/client/src/features/series/hooks/useSeriesById'; export const prefetch = async (store: ReturnType, { seriesId }: Params) => { invariant(seriesId); @@ -19,14 +16,10 @@ export const prefetch = async (store: ReturnType, { seriesId }; export const SeriesPage = () => { - const { seriesId } = useParams(); - invariant(seriesId); - - const series = useSeriesById({ seriesId }); + type PrefetchReturnType = ReturnType; + const { modules, series } = useLoaderData>(); invariant(series); - const modules = useRecommended({ referenceId: seriesId }); - return ( <> {`${series.title} - AremaTV`} @@ -41,12 +34,8 @@ export const SeriesPage = () => { />
-

- -

-
- -
+

{series.title}

+
{series.description}
diff --git a/workspaces/client/src/pages/timetable/components/NewTimetableFeatureDialog.tsx b/workspaces/client/src/pages/timetable/components/NewTimetableFeatureDialog.tsx index ce0f9224a..fc3af12c7 100644 --- a/workspaces/client/src/pages/timetable/components/NewTimetableFeatureDialog.tsx +++ b/workspaces/client/src/pages/timetable/components/NewTimetableFeatureDialog.tsx @@ -29,7 +29,7 @@ export const NewTimetableFeatureDialog = ({ isOpen }: Props) => { 引き続き皆様に快適にご利用いただけるよう、サービスの改善に努めてまいります。今後ともどうぞよろしくお願いいたします。

- +
- +
+ +
+
+ ); diff --git a/workspaces/client/src/pages/timetable/components/ProgramDetailDialog.tsx b/workspaces/client/src/pages/timetable/components/ProgramDetailDialog.tsx index 41e0ec14c..af4994ca3 100644 --- a/workspaces/client/src/pages/timetable/components/ProgramDetailDialog.tsx +++ b/workspaces/client/src/pages/timetable/components/ProgramDetailDialog.tsx @@ -1,5 +1,5 @@ import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { ReactElement } from 'react'; import { Link } from 'react-router'; import { ArrayValues } from 'type-fest'; @@ -32,7 +32,9 @@ export const ProgramDetailDialog = ({ isOpen, program }: Props): ReactElement =>
@@ -46,7 +48,9 @@ export const ProgramDetailDialog = ({ isOpen, program }: Props): ReactElement =>
diff --git a/workspaces/client/src/pages/timetable/components/ProgramList.tsx b/workspaces/client/src/pages/timetable/components/ProgramList.tsx index c15579607..173dac4eb 100644 --- a/workspaces/client/src/pages/timetable/components/ProgramList.tsx +++ b/workspaces/client/src/pages/timetable/components/ProgramList.tsx @@ -1,6 +1,6 @@ import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; -import { DateTime } from 'luxon'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; +import dayjs from 'dayjs'; import { ReactElement } from 'react'; import { ArrayValues } from 'type-fest'; @@ -18,9 +18,9 @@ export const ProgramList = ({ channelId, programList }: Props): ReactElement =>
{programList.map((program) => { - const startAt = DateTime.fromISO(program.startAt); - const endAt = DateTime.fromISO(program.endAt); - const duration = endAt.diff(startAt, 'minutes').minutes; + const startAt = dayjs(program.startAt); + const endAt = dayjs(program.endAt); + const duration = endAt.diff(startAt, 'minute'); const height = HEIGHT_ONE_HOUR * (duration / 60); return ( diff --git a/workspaces/client/src/pages/timetable/components/TimelineYAxis.tsx b/workspaces/client/src/pages/timetable/components/TimelineYAxis.tsx index c4eb15df4..f43ab6705 100644 --- a/workspaces/client/src/pages/timetable/components/TimelineYAxis.tsx +++ b/workspaces/client/src/pages/timetable/components/TimelineYAxis.tsx @@ -7,7 +7,8 @@ export const TimelineYAxis = (): ReactElement => { return (
{hour}
diff --git a/workspaces/client/src/pages/timetable/components/TimetablePage.tsx b/workspaces/client/src/pages/timetable/components/TimetablePage.tsx index 4c95964a3..0f76ada6a 100644 --- a/workspaces/client/src/pages/timetable/components/TimetablePage.tsx +++ b/workspaces/client/src/pages/timetable/components/TimetablePage.tsx @@ -1,4 +1,4 @@ -import { DateTime } from 'luxon'; +import dayjs from 'dayjs'; import invariant from 'tiny-invariant'; import { createStore } from '@wsh-2025/client/src/app/createStore'; @@ -10,9 +10,9 @@ import { TimelineYAxis } from '@wsh-2025/client/src/pages/timetable/components/T import { useShownNewFeatureDialog } from '@wsh-2025/client/src/pages/timetable/hooks/useShownNewFeatureDialog'; export const prefetch = async (store: ReturnType) => { - const now = DateTime.now(); - const since = now.startOf('day').toISO(); - const until = now.endOf('day').toISO(); + const now = dayjs(); + const since = now.startOf('day').toISOString(); + const until = now.endOf('day').toISOString(); const channels = await store.getState().features.channel.fetchChannels(); const programs = await store.getState().features.timetable.fetchTimetable({ since, until }); diff --git a/workspaces/client/src/pages/timetable/hooks/useEpisode.ts b/workspaces/client/src/pages/timetable/hooks/useEpisode.ts index f6d7677c9..a1c13bb66 100644 --- a/workspaces/client/src/pages/timetable/hooks/useEpisode.ts +++ b/workspaces/client/src/pages/timetable/hooks/useEpisode.ts @@ -1,5 +1,5 @@ import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { useEffect, useState } from 'react'; import { episodeService } from '@wsh-2025/client/src/features/episode/services/episodeService'; diff --git a/workspaces/client/src/pages/timetable/hooks/useSelectedProgramId.ts b/workspaces/client/src/pages/timetable/hooks/useSelectedProgramId.ts index 13d4b9d8c..0a269c0c4 100644 --- a/workspaces/client/src/pages/timetable/hooks/useSelectedProgramId.ts +++ b/workspaces/client/src/pages/timetable/hooks/useSelectedProgramId.ts @@ -1,5 +1,5 @@ import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { ArrayValues } from 'type-fest'; import { useStore } from '@wsh-2025/client/src/app/StoreContext'; diff --git a/workspaces/client/src/pages/timetable/stores/createTimetablePageStoreSlice.ts b/workspaces/client/src/pages/timetable/stores/createTimetablePageStoreSlice.ts index ed190b39b..e7327442d 100644 --- a/workspaces/client/src/pages/timetable/stores/createTimetablePageStoreSlice.ts +++ b/workspaces/client/src/pages/timetable/stores/createTimetablePageStoreSlice.ts @@ -1,8 +1,7 @@ import { lens } from '@dhmk/zustand-lens'; import { StandardSchemaV1 } from '@standard-schema/spec'; -import * as schema from '@wsh-2025/schema/src/api/schema'; +import type * as schema from '@wsh-2025/schema/src/openapi/schema'; import { produce } from 'immer'; -import _ from 'lodash'; import { ArrayValues } from 'type-fest'; import { DEFAULT_WIDTH } from '@wsh-2025/client/src/features/timetable/constants/grid_size'; @@ -24,6 +23,27 @@ interface TimetablePageActions { selectProgram: (program: Program | null) => void; } +// 指定された時間内に連続して呼び出された場合 +// 最後の呼び出しから指定時間が経過した後にのみ関数を実行する +function debounce(func: () => void, wait: number): () => void { + let timeoutId: ReturnType | null = null; + + return function (): void { + // 既存のタイマーがあればクリアする + if (timeoutId != null) { + clearTimeout(timeoutId); + } + + // 新しいタイマーを設定する + timeoutId = setTimeout(() => { + // 指定時間経過後に元の関数を直接呼び出す + func(); + // 実行後にタイマーIDをリセット + timeoutId = null; + }, wait); + }; +} + export const createTimetablePageStoreSlice = () => { return lens((set, _get) => ({ changeColumnWidth: (params: { channelId: string; delta: number }) => { @@ -41,7 +61,7 @@ export const createTimetablePageStoreSlice = () => { }, columnWidthRecord: {}, currentUnixtimeMs: 0, - refreshCurrentUnixtimeMs: _.debounce(() => { + refreshCurrentUnixtimeMs: debounce(() => { set(() => ({ currentUnixtimeMs: Date.now(), })); diff --git a/workspaces/client/src/setups/dayjs.ts b/workspaces/client/src/setups/dayjs.ts new file mode 100644 index 000000000..3dd3aec8a --- /dev/null +++ b/workspaces/client/src/setups/dayjs.ts @@ -0,0 +1,10 @@ +import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; +import timezone from 'dayjs/plugin/timezone'; +import utc from 'dayjs/plugin/utc'; + +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(duration); + +dayjs.tz.setDefault('Asia/Tokyo'); diff --git a/workspaces/client/src/setups/luxon.ts b/workspaces/client/src/setups/luxon.ts deleted file mode 100644 index 48132ca90..000000000 --- a/workspaces/client/src/setups/luxon.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Settings } from 'luxon'; - -declare module 'luxon' { - interface TSSettings { - throwOnInvalid: true; - } -} - -Settings.defaultZone = 'Asia/Tokyo'; -Settings.throwOnInvalid = true; diff --git a/workspaces/client/src/setups/polyfills.ts b/workspaces/client/src/setups/polyfills.ts deleted file mode 100644 index 0077ca803..000000000 --- a/workspaces/client/src/setups/polyfills.ts +++ /dev/null @@ -1,3 +0,0 @@ -import 'core-js'; -import 'view-transitions-polyfill'; -import 'setimmediate'; diff --git a/workspaces/client/src/setups/unocss.ts b/workspaces/client/src/setups/unocss.ts index d8e91da31..2b4989832 100644 --- a/workspaces/client/src/setups/unocss.ts +++ b/workspaces/client/src/setups/unocss.ts @@ -1,72 +1,2 @@ -import { IconifyJSON } from '@iconify/types'; -import presetIcons from '@unocss/preset-icons/browser'; -import presetWind3 from '@unocss/preset-wind3'; -import initUnocssRuntime, { defineConfig } from '@unocss/runtime'; - -async function init() { - await initUnocssRuntime({ - defaults: defineConfig({ - layers: { - default: 1, - icons: 0, - preflights: 0, - reset: -1, - }, - preflights: [ - { - getCSS: () => import('@unocss/reset/tailwind-compat.css?raw').then(({ default: css }) => css), - layer: 'reset', - }, - { - getCSS: () => /* css */ ` - @view-transition { - navigation: auto; - } - html, - :host { - font-family: 'Noto Sans JP', sans-serif !important; - } - video { - max-height: 100%; - max-width: 100%; - } - `, - }, - { - getCSS: () => /* css */ ` - @keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } - } - `, - }, - ], - presets: [ - presetWind3(), - presetIcons({ - collections: { - bi: () => import('@iconify/json/json/bi.json').then((m): IconifyJSON => m.default as IconifyJSON), - bx: () => import('@iconify/json/json/bx.json').then((m): IconifyJSON => m.default as IconifyJSON), - 'fa-regular': () => - import('@iconify/json/json/fa-regular.json').then((m): IconifyJSON => m.default as IconifyJSON), - 'fa-solid': () => - import('@iconify/json/json/fa-solid.json').then((m): IconifyJSON => m.default as IconifyJSON), - fluent: () => import('@iconify/json/json/fluent.json').then((m): IconifyJSON => m.default as IconifyJSON), - 'line-md': () => - import('@iconify/json/json/line-md.json').then((m): IconifyJSON => m.default as IconifyJSON), - 'material-symbols': () => - import('@iconify/json/json/material-symbols.json').then((m): IconifyJSON => m.default as IconifyJSON), - }, - }), - ], - }), - }); -} - -init().catch((err: unknown) => { - throw err; -}); +import '@unocss/reset/tailwind-compat.css'; +import 'uno.css'; diff --git a/workspaces/client/uno.config.ts b/workspaces/client/uno.config.ts new file mode 100644 index 000000000..768a797ad --- /dev/null +++ b/workspaces/client/uno.config.ts @@ -0,0 +1,58 @@ +import type { IconifyJSON } from '@iconify/types'; +import presetWind3 from '@unocss/preset-wind3'; +import { defineConfig, presetIcons } from 'unocss'; + +// eslint-disable-next-line @typescript-eslint/no-unsafe-call +export default defineConfig({ + layers: { + default: 1, + icons: 0, + preflights: 0, + reset: -1, + }, + preflights: [ + { + getCSS: () => /* css */ ` + @view-transition { + navigation: auto; + } + html, + :host { + font-family: 'Noto Sans JP', sans-serif !important; + } + video { + max-height: 100%; + max-width: 100%; + } + `, + }, + { + getCSS: () => /* css */ ` + @keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + `, + }, + ], + presets: [ + presetWind3(), + presetIcons({ + collections: { + bi: () => import('@iconify/json/json/bi.json').then((m): IconifyJSON => m.default as IconifyJSON), + bx: () => import('@iconify/json/json/bx.json').then((m): IconifyJSON => m.default as IconifyJSON), + 'fa-regular': () => + import('@iconify/json/json/fa-regular.json').then((m): IconifyJSON => m.default as IconifyJSON), + 'fa-solid': () => import('@iconify/json/json/fa-solid.json').then((m): IconifyJSON => m.default as IconifyJSON), + fluent: () => import('@iconify/json/json/fluent.json').then((m): IconifyJSON => m.default as IconifyJSON), + 'line-md': () => import('@iconify/json/json/line-md.json').then((m): IconifyJSON => m.default as IconifyJSON), + 'material-symbols': () => + import('@iconify/json/json/material-symbols.json').then((m): IconifyJSON => m.default as IconifyJSON), + }, + }), + ], +}); diff --git a/workspaces/client/webpack.config.mjs b/workspaces/client/webpack.config.mjs index 9164a996e..e58dabdd0 100644 --- a/workspaces/client/webpack.config.mjs +++ b/workspaces/client/webpack.config.mjs @@ -1,12 +1,14 @@ import path from 'node:path'; +import UnoCSS from '@unocss/webpack'; +import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import webpack from 'webpack'; /** @type {import('webpack').Configuration} */ const config = { - devtool: 'inline-source-map', + devtool: 'source-map', entry: './src/main.tsx', - mode: 'none', + mode: 'production', module: { rules: [ { @@ -18,6 +20,7 @@ const config = { use: { loader: 'babel-loader', options: { + cacheDirectory: true, presets: [ [ '@babel/preset-env', @@ -34,6 +37,10 @@ const config = { }, }, }, + { + test: /\.css$/, + use: [MiniCssExtractPlugin.loader, "css-loader"], + }, { test: /\.png$/, type: 'asset/inline', @@ -51,22 +58,22 @@ const config = { }, ], }, + optimization: { + realContentHash: true, + }, output: { chunkFilename: 'chunk-[contenthash].js', - chunkFormat: false, - filename: 'main.js', + chunkFormat: 'module', + filename: '[name].js', path: path.resolve(import.meta.dirname, './dist'), publicPath: 'auto', }, plugins: [ - new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }), + UnoCSS(), + new MiniCssExtractPlugin(), new webpack.EnvironmentPlugin({ API_BASE_URL: '/api', NODE_ENV: '' }), ], resolve: { - alias: { - '@ffmpeg/core$': path.resolve(import.meta.dirname, 'node_modules', '@ffmpeg/core/dist/umd/ffmpeg-core.js'), - '@ffmpeg/core/wasm$': path.resolve(import.meta.dirname, 'node_modules', '@ffmpeg/core/dist/umd/ffmpeg-core.wasm'), - }, extensions: ['.js', '.cjs', '.mjs', '.ts', '.cts', '.mts', '.tsx', '.jsx'], }, }; diff --git a/workspaces/configs/eslint.config.mjs b/workspaces/configs/eslint.config.mjs index a6955e4f6..b4a39e01f 100644 --- a/workspaces/configs/eslint.config.mjs +++ b/workspaces/configs/eslint.config.mjs @@ -2,12 +2,14 @@ import eslint from '@eslint/js'; import * as eslintConfigPrettier from 'eslint-config-prettier'; import eslintPluginImport from 'eslint-plugin-import'; import eslintPluginReact from 'eslint-plugin-react'; +import * as regexPlugin from 'eslint-plugin-regexp'; import eslintPluginSort from 'eslint-plugin-sort'; import globals from 'globals'; import tseslint from 'typescript-eslint'; /** @type {import('eslint').Linter.Config[]} */ const configs = [ + regexPlugin.configs['flat/recommended'], { files: ['**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}'], languageOptions: { diff --git a/workspaces/configs/package.json b/workspaces/configs/package.json index 82b244fec..dc631c60b 100644 --- a/workspaces/configs/package.json +++ b/workspaces/configs/package.json @@ -19,6 +19,7 @@ "typescript-eslint": "8.16.0" }, "devDependencies": { - "@types/node": "22.10.0" + "@types/node": "22.10.0", + "eslint-plugin-regexp": "2.7.0" } } diff --git a/workspaces/schema/src/api/schema.ts b/workspaces/schema/src/api/schema.ts deleted file mode 100644 index ed327fd43..000000000 --- a/workspaces/schema/src/api/schema.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Compile, TypeBox, Valibot, Zod } from '@sinclair/typemap'; - -import * as openapiSchema from '@wsh-2025/schema/src/openapi/schema'; - -export const getChannelsRequestQuery = Compile(TypeBox(openapiSchema.getChannelsRequestQuery)); -export const getChannelsResponse = Compile(TypeBox(openapiSchema.getChannelsResponse)); -export const getChannelByIdRequestParams = Compile(TypeBox(openapiSchema.getChannelByIdRequestParams)); -export const getChannelByIdResponse = Compile(TypeBox(openapiSchema.getChannelByIdResponse)); -export const getEpisodesRequestQuery = Compile(TypeBox(openapiSchema.getEpisodesRequestQuery)); -export const getEpisodesResponse = Compile(TypeBox(openapiSchema.getEpisodesResponse)); -export const getEpisodeByIdRequestParams = Compile(TypeBox(openapiSchema.getEpisodeByIdRequestParams)); -export const getEpisodeByIdResponse = Compile(TypeBox(openapiSchema.getEpisodeByIdResponse)); -export const getSeriesRequestQuery = Compile(Valibot(openapiSchema.getSeriesRequestQuery)); -export const getSeriesResponse = Compile(Valibot(openapiSchema.getSeriesResponse)); -export const getSeriesByIdRequestParams = Compile(Valibot(openapiSchema.getSeriesByIdRequestParams)); -export const getSeriesByIdResponse = Compile(Valibot(openapiSchema.getSeriesByIdResponse)); -export const getTimetableRequestQuery = Compile(Valibot(openapiSchema.getTimetableRequestQuery)); -export const getTimetableResponse = Compile(Valibot(openapiSchema.getTimetableResponse)); -export const getProgramsRequestQuery = Compile(Valibot(openapiSchema.getProgramsRequestQuery)); -export const getProgramsResponse = Compile(Valibot(openapiSchema.getProgramsResponse)); -export const getProgramByIdRequestParams = Compile(Valibot(openapiSchema.getProgramByIdRequestParams)); -export const getProgramByIdResponse = Compile(Valibot(openapiSchema.getProgramByIdResponse)); -export const getRecommendedModulesRequestParams = Compile(Valibot(openapiSchema.getRecommendedModulesRequestParams)); -export const getRecommendedModulesResponse = Compile(Valibot(openapiSchema.getRecommendedModulesResponse)); -export const signInRequestBody = Compile(Zod(openapiSchema.signInRequestBody)); -export const signInResponse = Compile(Zod(openapiSchema.signInResponse)); -export const signUpRequestBody = Compile(Zod(openapiSchema.signUpRequestBody)); -export const signUpResponse = Compile(Zod(openapiSchema.signUpResponse)); -export const getUserResponse = Compile(Zod(openapiSchema.getUserResponse)); diff --git a/workspaces/schema/src/openapi/schema.ts b/workspaces/schema/src/openapi/schema.ts index fb64a2f3d..2b6a7e980 100644 --- a/workspaces/schema/src/openapi/schema.ts +++ b/workspaces/schema/src/openapi/schema.ts @@ -179,24 +179,39 @@ export const getRecommendedModulesRequestParams = z.object({ referenceId: z.string(), }); export const getRecommendedModulesResponse = z.array( - recommendedModule.extend({ - items: z.array( - recommendedItem.extend({ - series: series - .extend({ - episodes: z.array(episode.extend({})), - }) - .nullable(), - episode: episode - .extend({ - series: series.extend({ - episodes: z.array(episode.extend({})), - }), - }) - .nullable(), - }), - ), - }), + recommendedModule + .pick({ + id: true, + title: true, + type: true, + }) + .extend({ + items: z.array( + recommendedItem.extend({ + series: series + .pick({ + id: true, + title: true, + thumbnailUrl: true, + }) + .nullable(), + episode: episode + .pick({ + id: true, + description: true, + thumbnailUrl: true, + title: true, + premium: true, + }) + .extend({ + series: series.pick({ + title: true, + }), + }) + .nullable(), + }), + ), + }), ); // POST /signIn diff --git a/workspaces/server/package.json b/workspaces/server/package.json index 456f1fbd3..e3586b3f1 100644 --- a/workspaces/server/package.json +++ b/workspaces/server/package.json @@ -11,6 +11,7 @@ "start": "wireit" }, "dependencies": { + "@fastify/compress": "8.0.1", "@fastify/cookie": "11.0.2", "@fastify/cors": "10.0.1", "@fastify/session": "11.1.0", diff --git a/workspaces/server/src/api.ts b/workspaces/server/src/api.ts index e1e080795..6c4850c83 100644 --- a/workspaces/server/src/api.ts +++ b/workspaces/server/src/api.ts @@ -32,8 +32,10 @@ export async function registerApi(app: FastifyInstance): Promise { await app.register(fastifySession, { cookie: { path: '/', + secure: false, }, cookieName: 'wsh-2025-session', + saveUninitialized: false, secret: randomBytes(32).toString('base64'), }); await app.register(fastifyZodOpenApiPlugin); @@ -72,7 +74,8 @@ export async function registerApi(app: FastifyInstance): Promise { } satisfies FastifyZodOpenApiSchema, handler: async function initialize(_req, reply) { await initializeDatabase(); - return reply.code(200).send({}); + reply.code(200).send({}); + return reply; }, }); @@ -107,7 +110,8 @@ export async function registerApi(app: FastifyInstance): Promise { return void 0; }, }); - return reply.code(200).send(channels); + reply.code(200).send(channels); + return reply; }, }); @@ -138,7 +142,8 @@ export async function registerApi(app: FastifyInstance): Promise { if (channel == null) { return reply.code(404).send(); } - return reply.code(200).send(channel); + reply.code(200).send(channel); + return reply; }, }); @@ -184,7 +189,8 @@ export async function registerApi(app: FastifyInstance): Promise { }, }, }); - return reply.code(200).send(episodes); + reply.code(200).send(episodes); + return reply; }, }); @@ -226,7 +232,8 @@ export async function registerApi(app: FastifyInstance): Promise { if (episode == null) { return reply.code(404).send(); } - return reply.code(200).send(episode); + reply.code(200).send(episode); + return reply; }, }); @@ -271,7 +278,8 @@ export async function registerApi(app: FastifyInstance): Promise { }, }, }); - return reply.code(200).send(series); + reply.code(200).send(series); + return reply; }, }); @@ -312,7 +320,8 @@ export async function registerApi(app: FastifyInstance): Promise { if (series == null) { return reply.code(404).send(); } - return reply.code(200).send(series); + reply.code(200).send(series); + return reply; }, }); @@ -348,7 +357,8 @@ export async function registerApi(app: FastifyInstance): Promise { ); }, }); - return reply.code(200).send(programs); + reply.code(200).send(programs); + return reply; }, }); @@ -399,7 +409,8 @@ export async function registerApi(app: FastifyInstance): Promise { }, }, }); - return reply.code(200).send(programs); + reply.code(200).send(programs); + return reply; }, }); @@ -446,7 +457,8 @@ export async function registerApi(app: FastifyInstance): Promise { if (program == null) { return reply.code(404).send(); } - return reply.code(200).send(program); + reply.code(200).send(program); + return reply; }, }); @@ -470,6 +482,11 @@ export async function registerApi(app: FastifyInstance): Promise { const database = getDatabase(); const modules = await database.query.recommendedModule.findMany({ + columns: { + id: true, + title: true, + type: true, + }, orderBy(module, { asc }) { return asc(module.order); }, @@ -483,23 +500,24 @@ export async function registerApi(app: FastifyInstance): Promise { }, with: { series: { - with: { - episodes: { - orderBy(episode, { asc }) { - return asc(episode.order); - }, - }, + columns: { + id: true, + title: true, + thumbnailUrl: true, }, }, episode: { + columns: { + id: true, + description: true, + thumbnailUrl: true, + title: true, + premium: true, + }, with: { series: { - with: { - episodes: { - orderBy(episode, { asc }) { - return asc(episode.order); - }, - }, + columns: { + title: true, }, }, }, @@ -508,7 +526,8 @@ export async function registerApi(app: FastifyInstance): Promise { }, }, }); - return reply.code(200).send(modules); + reply.code(200).send(modules); + return reply; }, }); @@ -543,7 +562,8 @@ export async function registerApi(app: FastifyInstance): Promise { const ret = schema.signInResponse.parse({ id: user.id, email: user.email }); req.session.set('id', ret.id.toString()); - return reply.code(200).send(user); + reply.code(200).send(user); + return reply; }, }); @@ -591,7 +611,8 @@ export async function registerApi(app: FastifyInstance): Promise { const ret = schema.signUpResponse.parse({ id: user.id, email: user.email }); req.session.set('id', ret.id.toString()); - return reply.code(200).send(ret); + reply.code(200).send(ret); + return reply; }, }); @@ -626,7 +647,8 @@ export async function registerApi(app: FastifyInstance): Promise { if (!user) { return reply.code(401).send(); } - return reply.code(200).send(user); + reply.code(200).send(user); + return reply; }, }); @@ -642,7 +664,8 @@ export async function registerApi(app: FastifyInstance): Promise { return reply.code(401).send(); } req.session.set('id', void 0); - return reply.code(200).send(); + reply.code(200).send(); + return reply; }, }); diff --git a/workspaces/server/src/index.ts b/workspaces/server/src/index.ts index 9ca2348f3..8d1c395e7 100644 --- a/workspaces/server/src/index.ts +++ b/workspaces/server/src/index.ts @@ -1,5 +1,6 @@ import '@wsh-2025/server/src/setups/luxon'; +import compress from '@fastify/compress'; import cors from '@fastify/cors'; import fastify from 'fastify'; @@ -15,10 +16,13 @@ async function main() { app.addHook('onSend', async (_req, reply) => { reply.headers({ - 'cache-control': 'no-store', 'x-robots-tag': 'noindex', }); }); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + await app.register(compress, { global: true }); + // 全てのオリジンからのリクエストを許可 app.register(cors, { origin: true, }); diff --git a/workspaces/server/src/ssr.tsx b/workspaces/server/src/ssr.tsx index 626670162..b3127496f 100644 --- a/workspaces/server/src/ssr.tsx +++ b/workspaces/server/src/ssr.tsx @@ -3,15 +3,12 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import fastifyStatic from '@fastify/static'; -import { StoreProvider } from '@wsh-2025/client/src/app/StoreContext'; import { createRoutes } from '@wsh-2025/client/src/app/createRoutes'; import { createStore } from '@wsh-2025/client/src/app/createStore'; import type { FastifyInstance } from 'fastify'; import { createStandardRequest } from 'fastify-standard-request-reply'; import htmlescape from 'htmlescape'; -import { StrictMode } from 'react'; -import { renderToString } from 'react-dom/server'; -import { createStaticHandler, createStaticRouter, StaticRouterProvider } from 'react-router'; +import { createStaticHandler } from 'react-router'; function getFiles(parent: string): string[] { const dirents = readdirSync(parent, { withFileTypes: true }); @@ -26,6 +23,7 @@ function getFilePaths(relativePath: string, rootDir: string): string[] { } export function registerSsr(app: FastifyInstance): void { + // 静的ファイルの配信を設定 app.register(fastifyStatic, { prefix: '/public/', root: [ @@ -42,7 +40,7 @@ export function registerSsr(app: FastifyInstance): void { // @ts-expect-error ................ const request = createStandardRequest(req, reply); - const store = createStore({}); + const store = createStore(); const handler = createStaticHandler(createRoutes(store)); const context = await handler.query(request); @@ -50,15 +48,6 @@ export function registerSsr(app: FastifyInstance): void { return reply.send(context); } - const router = createStaticRouter(handler.dataRoutes, context); - renderToString( - - store}> - - - , - ); - const rootDir = path.resolve(__dirname, '../../../'); const imagePaths = [ getFilePaths('public/images', rootDir), @@ -66,13 +55,14 @@ export function registerSsr(app: FastifyInstance): void { getFilePaths('public/logos', rootDir), ].flat(); - return reply.type('text/html').send(/* html */ ` + reply.type('text/html').send(/* html */ ` + ${imagePaths.map((imagePath) => ``).join('\n')} @@ -85,5 +75,6 @@ export function registerSsr(app: FastifyInstance): void { })}; `); + return reply; }); } diff --git a/workspaces/server/src/streams.tsx b/workspaces/server/src/streams.tsx index a1514de23..19d4ce95b 100644 --- a/workspaces/server/src/streams.tsx +++ b/workspaces/server/src/streams.tsx @@ -1,4 +1,3 @@ -import { randomBytes } from 'node:crypto'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -57,7 +56,8 @@ export function registerStreams(app: FastifyInstance): void { #EXT-X-ENDLIST `; - return reply.type('application/vnd.apple.mpegurl').send(playlist); + reply.type('application/vnd.apple.mpegurl').send(playlist); + return reply; }); app.get<{ @@ -118,16 +118,11 @@ export function registerStreams(app: FastifyInstance): void { ${chunkIdx === 0 ? '#EXT-X-DISCONTINUITY' : ''} #EXTINF:2.000000, /streams/${stream.id}/${String(chunkIdx).padStart(3, '0')}.ts - #EXT-X-DATERANGE:${[ - `ID="arema-${sequence}"`, - `START-DATE="${sequenceStartAt.toISOString()}"`, - `DURATION=2.0`, - `X-AREMA-INTERNAL="${randomBytes(3 * 1024 * 1024).toString('base64')}"`, - ].join(',')} `, ); } - return reply.type('application/vnd.apple.mpegurl').send(playlist.join('\n')); + reply.type('application/vnd.apple.mpegurl').send(playlist.join('\n')); + return reply; }); } diff --git a/workspaces/test/playwright.config.ts b/workspaces/test/playwright.config.ts index bf031167b..976102860 100644 --- a/workspaces/test/playwright.config.ts +++ b/workspaces/test/playwright.config.ts @@ -25,6 +25,6 @@ export default defineConfig({ use: { baseURL: BASE_URL, headless: true, - trace: 'off', + trace: 'retain-on-failure', }, }); diff --git a/workspaces/test/src/auth.test.ts b/workspaces/test/src/auth.test.ts index 7a01c7f88..cf3bd8bba 100644 --- a/workspaces/test/src/auth.test.ts +++ b/workspaces/test/src/auth.test.ts @@ -1,4 +1,5 @@ -import { test, expect } from '@playwright/test'; +import { expect, test } from '@playwright/test'; + import { waitForImageToLoad } from './utils'; test.describe('認証', () => { diff --git "a/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" "b/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" index 522a3c8c7..f9d6eea9c 100644 Binary files "a/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" and "b/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" differ diff --git "a/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\347\204\241\346\226\231\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" "b/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\347\204\241\346\226\231\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" index b71bbcab9..209817e38 100644 Binary files "a/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\347\204\241\346\226\231\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" and "b/workspaces/test/src/full-page.test.ts-snapshots/vrt-\343\202\250\343\203\224\343\202\275\343\203\274\343\203\211\343\203\232\343\203\274\343\202\270-\343\203\227\343\203\254\343\203\237\343\202\242\343\203\240---\347\204\241\346\226\231\343\203\246\343\203\274\343\202\266\343\203\274--Desktop-Chrome-darwin.png" differ