{"id":26923103,"url":"https://github.com/yurilopesm/cc-linter-exercise","last_synced_at":"2025-07-15T21:34:05.678Z","repository":{"id":284652140,"uuid":"955599851","full_name":"YuriLopesM/cc-linter-exercise","owner":"YuriLopesM","description":"Resolution for \"Topic 7 - Functions\" of Clean Code college class","archived":false,"fork":false,"pushed_at":"2025-03-27T00:24:31.000Z","size":82,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T01:27:52.405Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YuriLopesM.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-26T22:33:59.000Z","updated_at":"2025-03-27T00:24:34.000Z","dependencies_parsed_at":"2025-03-27T01:27:56.229Z","dependency_job_id":"ecda19fb-e833-4beb-a0ac-a714c0469f67","html_url":"https://github.com/YuriLopesM/cc-linter-exercise","commit_stats":null,"previous_names":["yurilopesm/cc-linter-exercise"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuriLopesM%2Fcc-linter-exercise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuriLopesM%2Fcc-linter-exercise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuriLopesM%2Fcc-linter-exercise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YuriLopesM%2Fcc-linter-exercise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YuriLopesM","download_url":"https://codeload.github.com/YuriLopesM/cc-linter-exercise/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246735356,"owners_count":20825223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-02T00:39:01.893Z","updated_at":"2025-04-02T00:39:02.365Z","avatar_url":"https://github.com/YuriLopesM.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Clean Code - Linters\n\n_[PT-BR] only 'cause its a simple college project._\n\nEste repositório foi criado para resolução de exercícios do _Tópico 7 - Linters_ da grade **Clean Code**. [Modelo do Exercício.](https://gitlab.com/professor-rvenson/cleancode-2025-1/-/blob/main/exercicios/exercicio-linters.md?ref_type=heads)\n\n| **Linguagem Sorteada** | **Linter Escolhido** |\n|------------------------|----------------------|\n| JavaScript             | ESLint               |\n\n### Tabela de Conteúdos\n\n- [Clean Code - Linters](#clean-code-linters)\n   * [Sobre o Linter](#sobre-o-linter)\n   * [Instalação](#instalação)\n      + [Pré-Requisitos](#pré-requisitos)\n      + [Configuração Inicial](#configuração-inicial)\n   * [Integração da Ferramenta](#integração-da-ferramenta)\n      + [Regras](#regras)\n      + [Utilização](#utilização)\n   * [Automatização](#automatização)\n      + [Git Hooks](#git-hooks)\n      + [CI/CD](#cicd)\n   * [Guias de Estilo](#guias-de-estilo)\n   * [Exemplos](#exemplos)\n\n### Sobre o Linter\n\nESLint é a biblioteca para JavaScript/ECMAScript mais utilizada no mercado, criada em 2013 pelo desenvolvedor **Nicholas C. Zakas** (Yahoo!, Human Who Codes). A ferramenta é utilizada para padronizar o código, garantir a qualidade e evitar erros comuns em projetos.\n\nAlguns números da ferramenta: \n\n- 📥 **~50 milhões** de downloads semanais via npm\n- 🌟 **25.7k** de _stars_ e **+10k** _issues_ fechadas no GitHub\n- 💾 **+10k** commits \n\n### Instalação\n\nSeguindo a documentação oficial, iremos seguir este tutorial com a instalação da última versão disponível: **v9.23.0**.\n\n#### Pré-Requisitos\n\n**Node.js** (nas versões ^18.18.0, ^20.9.0 ou \u003e=21.1.0) instalado e com suporte a SSL.\n\n_Obs.: caso você esteja usando uma distribuição oficial do Node.js, o SSL sempre estará integrado_.\n\nArquivo **package.json** criado, para que o setup instale os pacotes corretamente.\n\n```bash\n# npm\nnpm init @eslint/config@latest\n\n# yarn\nyarn create @eslint/config\n\n# pnpm\npnpm create @eslint/config@latest\n\n# bun\nbun create @eslint/config@latest\n```\n\n#### Configuração Inicial\n\nApós rodar o comando acima, serão feitas algumas perguntas para criar o arquivo de configuração com base nas opções selecionadas.\n\nPara este projeto, criaremos um projeto JavaScript _vanilla_ com o seguinte setup: \n\n![Imagem da configuração utilizada neste projeto](./assets/setup-lint-example.png)\n\n### Integração da Ferramenta\n \n#### Regras\n\nO arquivo criado, `esling.config.mjs`, deve estar com essa configuração:\n\n```js\nimport { defineConfig } from \"eslint/config\";\nimport globals from \"globals\";\nimport js from \"@eslint/js\";\n\n\nexport default defineConfig([\n  { files: [\"**/*.{js,mjs,cjs}\"] },\n  { files: [\"**/*.{js,mjs,cjs}\"], languageOptions: { globals: globals.browser } },\n  { files: [\"**/*.{js,mjs,cjs}\"], plugins: { js }, extends: [\"js/recommended\"] },\n]);\n```\n\nPodemos então adicionar [Regras](https://eslint.org/docs/latest/rules/), que são o conceito principal da biblioteca: validar se o código atende a uma expectativa e o que fazer caso ele não atenda a mesma. Também podemos estender as configurações com opções adicionais específicas para a regra criada.\n\n**Gravidade das Regras**\n\n- **“off”** ou **0** - desativa a regra\n- **“warn”** ou **1** - ativa a regra como um aviso (não afeta o código de saída)\n- **“error”** ou **2** - ativa a regra como um erro (o código de saída será 1)\n\nNormalmente, as regras são utilizadas sempre como _error_, para forçar a conformidade do código. Utilize _warn_ caso queira que o ESLint reporte a violação da regra, mas não interrompa nenhum processo. Geralmente utilizamos este método ao inserir uma nova regra que eventualmente será alterada para _error_.\n\nExemplo: \n\n```js\nimport js from \"@eslint/js\";\nimport { defineConfig } from \"eslint/config\";\nimport globals from \"globals\";\n\n\nexport default defineConfig([\n  { files: [\"**/*.{js,mjs,cjs}\"] },\n  { files: [\"**/*.{js,mjs,cjs}\"], languageOptions: { globals: globals.browser } },\n  { \n    files: [\"**/*.{js,mjs,cjs}\"],\n    plugins: { js }, \n    extends: [\"js/recommended\"],\n    rules: {\n      \"no-unused-vars\": \"error\",\n      \"no-undef\": \"warn\",\n    },\n  },\n]);\n```\n\n#### Utilização\n\nPodemos rodar o ESLint da seguinte forma:\n\n\u003e Note que utilizamos o `.` para indicar que devemos verificar todos os arquivos, veja mais opções na [documentação oficial](https://eslint.org/docs/latest/use/command-line-interface)\n\n```bash\n# npm (via npx)\nnpx eslint .\n\n# yarn\nyarn dlx eslint .\n\n# pnpm\npnpm dlx eslint .\n\n# bun\nbunx eslint .\n```\n\nPara facilitar integrações e automatizações, podemos adicionar um script no arquivo `package.json`:\n\n```json\n// Exemplo somente com o npm, mas pode ser adicionado \n// qualquer outro gerenciador de pacotes citado acima\n{\n  \"scripts\": {\n    \"lint\": \"npx eslint .\"\n  }\n}\n```\n\nE rodar o comando:\n\n```bash\n# npm\nnpm run lint\n\n# yarn\nyarn lint\n\n# pnpm\npnpm lint\n\n# bun\nbun lint\n```\n### Automatização\n\nExistem várias maneiras de automatizar a execução do ESLint, mostraremos duas delas:\n\n#### Git Hooks\n\nGit Hooks são scripts que são executados automaticamente em determinados eventos do Git, como _commit_, _push_, _pull_ e _merge_. Podemos adicionar o ESLint em um _hook_ para que ele valide o código a cada _commit_.\n\nPara isso, iremos utilizar uma biblioteca chamada **Husky**. Abra a [documentação oficial](https://typicode.github.io/husky/get-started.html) para ter um guia de instalação detalhado sobre o assunto.\n\n```bash\n# npm\nnpm install --save-dev husky\nnpx husky init\n\n# yarn\nyarn add --dev husky\n# Devido algumas diferenças do yarn como gerenciador de pacotes, é necessário fazer o setup manualmente\n\n# pnpm\npnpm add --save-dev husky\npnpm exec husky init\n\n# bun\nbun add --dev husky\nbunx husky init\n```\n\nApós efetuar a instalação, será criado uma pasta chamada `.husky` na raiz do projeto, com um arquivo chamado `pre-commit`. Adicione neste arquivo o comando `npm run lint` que criamos anteriormente.\n\nAgora, para cada _commit_ que você fizer, o ESLint irá rodar e validar o código antes de permitir que o _commit_ seja efetuado.\n\n\u003e Há mais configurações que podem ser feitas para checar somente os arquivos que serão adicionados no _commit_, mas para facilitar o entendimento, não iremos abordar este assunto.\n\n#### CI/CD\n\nPodemos adicionar o ESLint em um _workflow_ do GitHub Actions, para que ele valide o código a cada _push_ ou _pull request_.\n\n```yaml\nname: Pipeline\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout código\n        uses: actions/checkout@v4\n\n      - name: Configurar Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n\n      - name: Instalar dependências\n        run: npm install\n\n      - name: Verificar ESLint # Esta etapa garantirá que o código esteja de acordo com as regras\n        run: npm run lint\n\n      - name: Rodar aplicação\n        run: npm run start\n```\n\n### Guias de Estilo\n\nO ESLint permite que você crie seu próprio guia de estilo, mas também permite que você utilize guias de estilo já prontos. Na instalação manual, você consegue diretamente pelo CLI escolher os três guias de estilo mais utilizados:\n\n- [Airbnb](https://www.npmjs.com/package/eslint-config-airbnb)\n- [Google](https://www.npmjs.com/package/eslint-config-google)\n- [Standard](https://www.npmjs.com/package/eslint-config-standard)\n\nNote que no nosso exemplo, utilizamos o guia de estilo `js/recommended`, que é um guia de estilo recomendado pela própria equipe do ESLint.\n\n```js\nimport js from \"@eslint/js\";\nimport { defineConfig } from \"eslint/config\";\n// ...\n\nexport default defineConfig([\n  // ...\n  { \n    files: [\"**/*.{js,mjs,cjs}\"],\n    plugins: { js }, \n    extends: [\"js/recommended\"] // aqui podemos usar qualquer configuração\n  },\n]);\n\n```\n\n\u003e Note que também podemos adicionar várias extensões, dependendo da complexidade do projeto e o que você deseja validar.\n\n\n### Exemplos\n\nExistem [diversas regras](https://eslint.org/docs/latest/rules/) que podemos configurar no ESLint, mas para facilitar o entendimento, iremos mostrar alguns exemplos de regras que são comuns em projetos JavaScript.\n\n**no-unused-vars** - Evita que variáveis sejam declaradas e não utilizadas.\n\n```js\n// ❌ Variável declarada, mas não utilizada\nlet x;\n\n// ❌ Variável que é modificada, mas não utilizada\nlet y = 10;\ny = 5;\n\n// ❌ Variável que chama a si mesma para efetuar uma modificação\nlet z = 0;\nz = z + 1;\n\n// ❌ Argumentos não utilizados\n(function(foo) {\n    return 5;\n})();\n\n// ❌ Funções recursivas não utilizadas\nfunction fact(n) {\n    if (n \u003c 2) return 1;\n    return n * fact(n - 1);\n}\n\n// ❌ Quando uma função desestrutura um array, itens não utilizados também acionarão a regra\nfunction getY([x, y]) {\n    return y;\n}\ngetY([\"a\", \"b\"]);\n\n// ✅ Variável utilizada\nlet a = 10;\nconsole.log(a);\n```\n**no-const-assign** - Evita que constantes sejam modificadas.\n\n```js\nconst x = 10;\nx = 5; // ❌\n\nconst y = 10;\ny += 5; // ❌\n\nconst z = 10;\nz++; // ❌\n\nfor (const a of [1, 2, 3]) { // ✅ A variável `a` é re-definida (não modificada) para cada iteração do loop\n    console.log(a);\n}\n```\n\n**no-duplicate-imports** - Evita que módulos sejam importados mais de uma vez.\n\n```js \n// ❌ Importação duplicada\nimport { foo } from \"./foo\";\nimport { bar } from \"./foo\";\n\n// ✅ Correto\n\nimport { foo, bar } from \"./foo\";\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyurilopesm%2Fcc-linter-exercise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyurilopesm%2Fcc-linter-exercise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyurilopesm%2Fcc-linter-exercise/lists"}