From d181c76dfdd58e0567c5eb84deafeee92a46517c Mon Sep 17 00:00:00 2001 From: Evandro Fonseca Junior Date: Sat, 10 Oct 2026 03:55:30 -0300 Subject: [PATCH] =?UTF-8?q?chore:=20remove=20c=C3=B3digo=20morto=20e=20pad?= =?UTF-8?q?roniza=20scripts=20e=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 27 +++ docs/PLAN.md | 0 package.json | 7 +- pnpm-lock.yaml | 167 ++++++++++++++++- server/package.json | 3 +- server/src/index.ts | 10 - server/src/lib/DownloadManager.ts | 1 - web/README.md | 73 -------- web/package.json | 1 - web/src/App.css | 290 ----------------------------- web/src/App.tsx | 1 - web/src/assets/react.svg | 1 - web/src/components/ui/Textarea.tsx | 22 --- 13 files changed, 191 insertions(+), 412 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 docs/PLAN.md delete mode 100644 web/README.md delete mode 100644 web/src/App.css delete mode 100644 web/src/assets/react.svg delete mode 100644 web/src/components/ui/Textarea.tsx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..509bf93 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 12.8.1 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - run: pnpm install --frozen-lockfile + - run: pnpm typecheck + - run: pnpm lint + - run: pnpm test + - run: pnpm build diff --git a/docs/PLAN.md b/docs/PLAN.md deleted file mode 100644 index e69de29..0000000 diff --git a/package.json b/package.json index 156df23..0eb7c56 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,13 @@ "dev:server": "pnpm --filter server dev", "dev:web": "pnpm --filter web dev", "build": "pnpm -r build", - "start": "pnpm --filter server start" + "start": "pnpm --filter server start", + "test": "pnpm -r --if-present test", + "lint": "pnpm -r --if-present lint", + "typecheck": "pnpm -r --if-present typecheck" }, "workspaces": [ "server", "web" ] } - - diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ec668fe..b4b68a8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,3 +1,161 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + pnpm: + specifier: 12.8.1 + version: 12.8.1 + +packages: + + '@pnpm/exe.android-arm64@12.8.1': + resolution: {integrity: sha512-siDxcidfz5eM6L2tJfik+i2bbUEw8UC7MZ3Yl2HYdRmqbdhHGAOQACtOOu6QVW4Jul4/w5wVKm+wM8ACtgh1Pg==} + cpu: [arm64] + os: [android] + + '@pnpm/exe.android-x64@12.8.1': + resolution: {integrity: sha512-0F/uqPRc3aN4vLHsa0f+6fTtmsigFQ9/yxEU43fionF//pNHEd5e97b3w/nKIgqYMCUQCJphmBRMA9Q8/wlo9Q==} + cpu: [x64] + os: [android] + + '@pnpm/exe.darwin-arm64@12.8.1': + resolution: {integrity: sha512-/rwavvMQJsl2RIxOHBnDF+4Gk+fhQFAY4M3PQZoKskJOEnaJcygG9p1xby6wcQcbS4d9dIubv09CQhufTgfmpw==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.8.1': + resolution: {integrity: sha512-htYt2gN7zqJKLhC99Ft6EUiO7myjZAZXfmGCTJUL1v+o7vE9hZdE1+fAkk4Oj1ZHNRti6b2woOxEkRkAusi8OQ==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.freebsd-x64@12.8.1': + resolution: {integrity: sha512-PB5BULNgytxvExoOXUUeseS/DcpPENs+cg3iA6xHHeaLT4ctEGKSGXEbuj7USeqvo8JBpAx039hivnbzGqDwnA==} + cpu: [x64] + os: [freebsd] + + '@pnpm/exe.linux-arm64-musl@12.8.1': + resolution: {integrity: sha512-kKeyC/ArjrgdciQRBrOL0j9HtOI4gDRgoyP+eJ1CQKyadpKlf/DhDDyspXe07R3B9KagTVLUF2nlt6Dr5quFIg==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.8.1': + resolution: {integrity: sha512-q4s9a9X2O3N9aeUFooW24orNrxvu20+jyVUFR5RanPCqOKKPBrgs2iywMkBBx1aXkkzdWT54/mfz8Be8sJlWEw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-ppc64@12.8.1': + resolution: {integrity: sha512-F7XSjKJthwCh/L6abZiMpAfo2Cm61SZIT3e4dfgiIjESndlWaXCnfLKngSgZ/SEMsdmHT6dud3+kWIB3tw0/xQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-riscv64@12.8.1': + resolution: {integrity: sha512-z1ecpIK/ZY08Unk69KWWE9867oaKUytGUjrHnBoGFAAhsK+q+0cfvBH+f5fWobJ7FX97leMlLO+gkJolddM45Q==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-s390x@12.8.1': + resolution: {integrity: sha512-KU6tnrBfu4uKXTq6N5qJwSm8FSrs9Wc8b5AUEsHK9bRXwNdsZ1/lRxG1++X29SKRW9OSNuDSjxASv5mAvGo1gA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.8.1': + resolution: {integrity: sha512-eUE8BWJkDr2tJb/yrk0yVnszlmNqFarVxUlqiZ9BAkct28Nq/5g2H0tvMDmPA7fAQW3STNj+omJPPRVT+4s5sQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.8.1': + resolution: {integrity: sha512-8bDZ0lZlCdi2rvnFul7EYgcC7zKeWSe76y8JV2oXobaS8p9i9d6PSf6LgLtTM0fI7R9Oh4eLCbveXyNDMmvZ+g==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.8.1': + resolution: {integrity: sha512-MsT0dlrRxnCRCHCaosNbhWpEiAFnFuMEu3KuDJDU41BXgTwiINxU8goloUSUDejWZUqKaUqNC/qUTihl9nFtqg==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.8.1': + resolution: {integrity: sha512-SWtPe0PsbTTk//gJND10tMdOfCYjrkq5+qV49hzVhY7xz2iJ339Rc+xwASlcvbwTfrvH39YNqpKYibD+CRGLwA==} + cpu: [x64] + os: [win32] + + pnpm@12.8.1: + resolution: {integrity: sha512-9kupB1B/XOr+BsjTjmBS0BeURFgOwSed3Vv8EctIqoomRLZlmOB+dh2oSHKp/FfV+QK4f6SdAkGY1VhhKqu+RQ==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.android-arm64@12.8.1': + optional: true + + '@pnpm/exe.android-x64@12.8.1': + optional: true + + '@pnpm/exe.darwin-arm64@12.8.1': + optional: true + + '@pnpm/exe.darwin-x64@12.8.1': + optional: true + + '@pnpm/exe.freebsd-x64@12.8.1': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.8.1': + optional: true + + '@pnpm/exe.linux-arm64@12.8.1': + optional: true + + '@pnpm/exe.linux-ppc64@12.8.1': + optional: true + + '@pnpm/exe.linux-riscv64@12.8.1': + optional: true + + '@pnpm/exe.linux-s390x@12.8.1': + optional: true + + '@pnpm/exe.linux-x64-musl@12.8.1': + optional: true + + '@pnpm/exe.linux-x64@12.8.1': + optional: true + + '@pnpm/exe.win32-arm64@12.8.1': + optional: true + + '@pnpm/exe.win32-x64@12.8.1': + optional: true + + pnpm@12.8.1: + optionalDependencies: + '@pnpm/exe.android-arm64': 12.8.1 + '@pnpm/exe.android-x64': 12.8.1 + '@pnpm/exe.darwin-arm64': 12.8.1 + '@pnpm/exe.darwin-x64': 12.8.1 + '@pnpm/exe.freebsd-x64': 12.8.1 + '@pnpm/exe.linux-arm64': 12.8.1 + '@pnpm/exe.linux-arm64-musl': 12.8.1 + '@pnpm/exe.linux-ppc64': 12.8.1 + '@pnpm/exe.linux-riscv64': 12.8.1 + '@pnpm/exe.linux-s390x': 12.8.1 + '@pnpm/exe.linux-x64': 12.8.1 + '@pnpm/exe.linux-x64-musl': 12.8.1 + '@pnpm/exe.win32-arm64': 12.8.1 + '@pnpm/exe.win32-x64': 12.8.1 + +--- lockfileVersion: '9.0' settings: @@ -61,9 +219,6 @@ importers: tailwind-merge: specifier: ^3.4.0 version: 3.4.0 - uuid: - specifier: ^13.0.0 - version: 13.0.0 zod: specifier: ^3.25.76 version: 3.25.76 @@ -1859,10 +2014,6 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - uuid@13.0.0: - resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} - hasBin: true - vite@7.2.4: resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3576,8 +3727,6 @@ snapshots: dependencies: punycode: 2.3.1 - uuid@13.0.0: {} - vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0): dependencies: esbuild: 0.25.12 diff --git a/server/package.json b/server/package.json index 75c2a43..a800ad4 100644 --- a/server/package.json +++ b/server/package.json @@ -7,7 +7,8 @@ "scripts": { "dev": "tsx src/index.ts", "build": "tsc -p tsconfig.json", - "start": "node dist/index.js" + "start": "node dist/index.js", + "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { "@fastify/cors": "^11.2.0", diff --git a/server/src/index.ts b/server/src/index.ts index 7c8c79e..5d71b61 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -51,16 +51,6 @@ app.get("/health", async () => { return { status: "ok" }; }); -const streamQuerySchema = z.object({ - url: z.string().url("URL inválida").startsWith("http", "Apenas HTTP/HTTPS permitidos"), - // Offset opcional em bytes para retomar download. - offset: z - .string() - .regex(/^\d+$/) - .transform((value) => Number.parseInt(value, 10)) - .optional(), -}); - const downloadManager = new DownloadManager(agent); // Helper to get session from header diff --git a/server/src/lib/DownloadManager.ts b/server/src/lib/DownloadManager.ts index 3b2ccd0..ac5781d 100644 --- a/server/src/lib/DownloadManager.ts +++ b/server/src/lib/DownloadManager.ts @@ -25,7 +25,6 @@ export type DownloadTask = { // Map to store active task metadata in memory (for speed) // Ideally this would be persisted to JSON in the session folder for crash recovery const tasks = new Map(); -const agent = new Dispatcher(); // Should use the global agent from index.ts ideally, or pass it in. export class DownloadManager { diff --git a/web/README.md b/web/README.md deleted file mode 100644 index d2e7761..0000000 --- a/web/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## React Compiler - -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` diff --git a/web/package.json b/web/package.json index ee6bacc..4b279f7 100644 --- a/web/package.json +++ b/web/package.json @@ -17,7 +17,6 @@ "react": "^19.2.0", "react-dom": "^19.2.0", "tailwind-merge": "^3.4.0", - "uuid": "^13.0.0", "zod": "^3.25.76" }, "devDependencies": { diff --git a/web/src/App.css b/web/src/App.css deleted file mode 100644 index 92614dd..0000000 --- a/web/src/App.css +++ /dev/null @@ -1,290 +0,0 @@ -.app-root { - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 2.5rem 1.5rem 3rem; - gap: 2.5rem; - background: radial-gradient(circle at top, #27272a 0, #09090b 45%, #020617 100%); -} - -.app-header { - max-width: 640px; - text-align: center; -} - -.app-header h1 { - font-size: 2rem; - margin-bottom: 0.5rem; -} - -.app-header p { - font-size: 0.98rem; - color: #e4e4e7; -} - -.app-header-meta { - margin-top: 0.5rem; - display: flex; - justify-content: center; - gap: 1rem; - flex-wrap: wrap; - font-size: 0.8rem; - color: #a1a1aa; -} - -.app-main { - width: 100%; - display: flex; - justify-content: center; - align-items: flex-start; - gap: 2rem; - max-width: 1200px; - margin: 0 auto; -} - -.download-form { - width: 100%; - max-width: 560px; - display: flex; - flex-direction: column; - gap: 0.75rem; - padding: 1.5rem 1.75rem; - border-radius: 1rem; - border: 1px solid rgba(63, 63, 70, 0.9); - background: radial-gradient(circle at top left, #18181b 0, #020617 60%); - box-shadow: - 0 18px 40px rgba(0, 0, 0, 0.7), - 0 0 0 1px rgba(24, 24, 27, 0.9); -} - -.field-label { - font-size: 0.9rem; - font-weight: 500; -} - -.field-helper { - font-size: 0.78rem; - color: #a1a1aa; - margin-top: -0.1rem; -} - -.url-input { - padding: 0.75rem 0.9rem; - border-radius: 0.5rem; - border: 1px solid #27272a; - background-color: #09090b; - color: #f4f4f5; - font-size: 0.95rem; - resize: vertical; -} - -.url-input--multiline { - line-height: 1.4; -} - -.url-input:focus { - outline: 2px solid #4f46e5; - outline-offset: 1px; - border-color: transparent; -} - -.primary-button { - margin-top: 0.5rem; - padding: 0.75rem 1rem; - border-radius: 0.5rem; - border: none; - background: #4f46e5; - color: #f9fafb; - font-weight: 600; - font-size: 0.95rem; - cursor: pointer; - transition: background 180ms ease-out, transform 160ms ease-out; -} - -.primary-button:hover { - background: #4338ca; -} - -.primary-button:active { - transform: translateY(1px) scale(0.99); -} - -.primary-button:focus-visible { - outline: 2px solid #a5b4fc; - outline-offset: 2px; -} - -.error-text { - font-size: 0.85rem; - color: #f97373; -} - -.downloads-section { - width: 100%; - max-width: 620px; - margin-top: 0; - padding: 1.25rem 1.5rem; - border-radius: 1rem; - border: 1px solid rgba(63, 63, 70, 0.9); - background-color: rgba(9, 9, 11, 0.9); - backdrop-filter: blur(14px); -} - -.downloads-title { - font-size: 1rem; - margin-bottom: 0.5rem; -} - -.downloads-empty { - margin-top: 0.5rem; - font-size: 0.85rem; - color: #a1a1aa; -} - -.downloads-list { - list-style: none; - padding: 0; - margin: 0; - display: flex; - flex-direction: column; - gap: 0.75rem; -} - -.download-item { - padding: 0.6rem 0.1rem 0.7rem; - border-bottom: 1px solid rgba(39, 39, 42, 0.8); -} - -.download-item:last-of-type { - border-bottom: none; -} - -.download-main { - display: flex; - justify-content: space-between; - align-items: center; - gap: 0.75rem; - margin-bottom: 0.35rem; -} - -.download-url { - font-size: 0.8rem; - color: #e5e5e5; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.badge { - padding: 0.2rem 0.55rem; - border-radius: 999px; - font-size: 0.7rem; - font-weight: 500; -} - -.badge--pending { - background-color: rgba(39, 39, 42, 0.9); - color: #e5e5e5; -} - -.badge--downloading { - background-color: rgba(37, 99, 235, 0.18); - color: #bfdbfe; -} - -.badge--completed { - background-color: rgba(22, 163, 74, 0.25); - color: #bbf7d0; -} - -.badge--error { - background-color: rgba(239, 68, 68, 0.18); - color: #fecaca; -} - -.progress-wrapper { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.progress-bar { - flex: 1; - height: 0.4rem; - border-radius: 999px; - background-color: #18181b; - overflow: hidden; -} - -.progress-bar__fill { - height: 100%; - border-radius: inherit; - background: linear-gradient(to right, #4f46e5, #22c55e); - transition: width 160ms ease-out; -} - -.progress-label { - font-size: 0.75rem; - color: #e4e4e7; - width: 3ch; - text-align: right; -} - -.download-error { - margin-top: 0.1rem; - font-size: 0.78rem; - color: #fecaca; -} - -.download-meta { - display: flex; - flex-wrap: wrap; - gap: 0.4rem; - margin-top: 0.25rem; - font-size: 0.8rem; - color: #d4d4d8; -} - -.download-footer { - margin-top: 0.35rem; - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.75rem; -} - -.secondary-button { - padding: 0.35rem 0.75rem; - border-radius: 999px; - border: 1px solid #3f3f46; - background-color: transparent; - color: #e4e4e7; - font-size: 0.78rem; - font-weight: 500; - cursor: pointer; - transition: - background-color 160ms ease-out, - border-color 160ms ease-out, - transform 120ms ease-out; -} - -.secondary-button:hover { - background-color: rgba(63, 63, 70, 0.4); - border-color: #71717a; -} - -.secondary-button:active { - transform: translateY(1px) scale(0.99); -} - -@media (min-width: 768px) { - .app-header h1 { - font-size: 2.25rem; - } - - .download-form { - padding: 1.75rem 2rem; - } -} diff --git a/web/src/App.tsx b/web/src/App.tsx index 26d7981..febb914 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,4 +1,3 @@ -import "./App.css"; import { DownloadForm } from "./components/feature/DownloadForm"; import { DownloadItem } from "./components/feature/DownloadItem"; import { Layout } from "./components/ui/Layout"; diff --git a/web/src/assets/react.svg b/web/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/web/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/web/src/components/ui/Textarea.tsx b/web/src/components/ui/Textarea.tsx deleted file mode 100644 index f05f1f6..0000000 --- a/web/src/components/ui/Textarea.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from "react"; -import { cn } from "../../lib/utils"; - -export type TextareaProps = React.TextareaHTMLAttributes; - -const Textarea = React.forwardRef( - ({ className, ...props }, ref) => { - return ( -