{"id":21096696,"url":"https://github.com/pedrohvfernandes/url-shortening-system-with-node","last_synced_at":"2026-04-11T09:33:40.398Z","repository":{"id":228736341,"uuid":"774550972","full_name":"PedrohvFernandes/url-shortening-system-with-node","owner":"PedrohvFernandes","description":"Projeto desenvolvido para testar o Redis junto com Postgresql","archived":false,"fork":false,"pushed_at":"2024-04-04T15:59:04.000Z","size":132,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-21T02:08:49.385Z","etag":null,"topics":["docker","eslint","husky","nodejs","postgresql","redis","sql","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/PedrohvFernandes.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":"2024-03-19T18:40:28.000Z","updated_at":"2024-04-08T18:28:37.000Z","dependencies_parsed_at":"2024-03-20T08:26:27.918Z","dependency_job_id":"ca044a46-6ca7-46f0-87e5-e5ea614c8fee","html_url":"https://github.com/PedrohvFernandes/url-shortening-system-with-node","commit_stats":null,"previous_names":["pedrohvfernandes/url-shortening-system-with-node"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedrohvFernandes%2Furl-shortening-system-with-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedrohvFernandes%2Furl-shortening-system-with-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedrohvFernandes%2Furl-shortening-system-with-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedrohvFernandes%2Furl-shortening-system-with-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PedrohvFernandes","download_url":"https://codeload.github.com/PedrohvFernandes/url-shortening-system-with-node/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243538153,"owners_count":20307115,"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":["docker","eslint","husky","nodejs","postgresql","redis","sql","typescript"],"created_at":"2024-11-19T22:39:11.114Z","updated_at":"2025-12-29T09:12:25.219Z","avatar_url":"https://github.com/PedrohvFernandes.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Url Shortening System With Node.js And TypeScript\n\n### Logica do fluxo da aplicação\n\nEssa aplicação é para encurtamentos de *links*, tu passa pra ela um *link grande* e um *code pequeno*, ao acessar a minha aplicação passando esse code eu retorno a *url original(Link grande)*, e redireciono para a url original.\n\nE iremos anotar com o *redis* quantos acessos cada link teve para depois mostrar isso *analytics*\n\n### Anotações:\n\n- @types/node: Integração do TypeScript com o NodeJS, em relação a tipagem\n- Typescript: Adiciona suporte ao TypeScript\n- tsx: uma ferramenta permite executar codigo TS, convertendo para JS e executa\n- Npx: Uma ferramenta que ja vem instalada com node(Alem do npm) que ela faz ir no node_modules\u003e.bin e executa o comando que vc passar(./node_modules/.bin/tsc -h), nesse caso tsc, se não achar ele, o node  busca globalmente na internet\n- Então se eu der no terminal:\n  ```bash\n    ./node_modules/.bin/tsc --init\n    # Ou\n    npx tsc --init\n  ```\n  Irão fazer a mesma coisa, se o npx não achar o tsc ele procura esse comando na internet\n- Para achar uma config do tsconfig.json, basta ir no repositório tsconfig/bases [Configs para TS Node](https://github.com/tsconfig/bases) e pra cada versão do node, ele tem a config exata no readme, basta clicar ```@tsconfig/node20``` ou na versão mais atual do momento, e copiar o readme, ex:\n```\n{\n  \"$schema\": \"https://json.schemastore.org/tsconfig\",\n  \"display\": \"Node 20\",\n  \"_version\": \"20.1.0\",\n\n  \"compilerOptions\": {\n    \"lib\": [\"es2023\"],\n    \"module\": \"node16\",\n    \"target\": \"es2022\",\n\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"moduleResolution\": \"node16\"\n  }\n}\n```\nSe não, instalar \n```bash\nnpm install --save-dev @tsconfig/node20\nyarn add --dev @tsconfig/node20\n```\ne extender em tsconfig.json\n```json\n{\n  \"extends\": \"@tsconfig/node20/tsconfig.json\"\n}\n```\n- [O que é o node em si: callbacks, onde tudo começou](https://blog.rocketseat.com.br/callback-promises-e-async-await-tudo-o-que-voce-precisa-saber/)\n- Podemos usar a Ia para gerar o arquivo do Docker:\n```` \nCreate a docker compose file with two services, one postgres using bitnami postgres image and onde redis with bitnami redis. Expose ports. Save volumes\n````\n````yaml\nversion: '3.8'\n\nservices:\n  postgres:\n    image: 'bitnami/postgresql:latest'\n    ports:\n      - '5432:5432'\n    environment:\n      - POSTGRESQL_USERNAME=my_user\n      - POSTGRESQL_PASSWORD=my_password\n      - POSTGRESQL_DATABASE=my_database\n    volumes:\n      - postgres_data:/bitnami/postgresql/data\n\n  redis:\n    image: 'bitnami/redis:latest'\n    ports:\n      - '6379:6379'\n    volumes:\n      - redis_data:/bitnami/redis/data\n\nvolumes:\n  postgres_data:\n    driver: local\n  redis_data:\n    driver: local\n````\n```` \nSet redis password as docker\n````\n```yml\nversion: '3.8'\n\nservices:\n  postgres:\n    image: 'bitnami/postgresql:latest'\n    ports:\n      - '5432:5432'\n    environment:\n      - POSTGRESQL_USERNAME=my_user\n      - POSTGRESQL_PASSWORD=my_password\n      - POSTGRESQL_DATABASE=my_database\n    volumes:\n      - postgres_data:/bitnami/postgresql/data\n\n  redis:\n    image: 'bitnami/redis:latest'\n    ports:\n      - '6379:6379'\n    environment:\n      - REDIS_PASSWORD=my_redis_password\n    volumes:\n      - redis_data:/bitnami/redis/data\n\nvolumes:\n  postgres_data:\n    driver: local\n  redis_data:\n    driver: local\n```\n```\nSet postgres database and user\n```\n```yml\nversion: '3.8'\n\nservices:\n  postgres:\n    image: 'bitnami/postgresql:latest'\n    ports:\n      - '5432:5432'\n    environment:\n      - POSTGRESQL_USERNAME=my_user\n      - POSTGRESQL_PASSWORD=my_password\n      - POSTGRESQL_DATABASE=my_database\n    volumes:\n      - postgres_data:/bitnami/postgresql/data\n\n  redis:\n    image: 'bitnami/redis:latest'\n    ports:\n      - '6379:6379'\n    environment:\n      - REDIS_PASSWORD=my_redis_password\n    volumes:\n      - redis_data:/bitnami/redis/data\n\nvolumes:\n  postgres_data:\n    driver: local\n  redis_data:\n    driver: local\n```\n- Apos configurar o arquivo, [instalar](https://docs.docker.com/engine/install/) o docker,  wsl(Para *windows*) e executar o docker, basta dar um ```docker-compose up -d``` e ele ira subir os serviços, e para parar ```docker-compose down```\n- Usamos imagens da bitnami, pois elas ja vem prontas para produção, elas ja tem configurações de segurança, com senha e são otimizadas para produção\n- Por que os dois bancos ? O postgres é um banco relacional e estruturado, e o redis é um banco chave-valor, que é muito mais rápido que o postgres, e é muito usado para cache, e para armazenar dados que não precisam de muita segurança, como por exemplo, um contador de visitas, que não precisa ser exato, e sim rápido. ​​Redis, bom para, cache, lock distribuído, lógica que usa tempo para expirar, sistema de enfileiramento, o redis pode ser usado para sistema de ranking etc. A parte de pub/sub é a parte mais firme do redis. No redis consegue salvar o resultado de uma operação para que as próximas pessoas que precisam daqueles dados tenham acesso a isso no futuro de uma maneira mais rápida através da sua arquitetura de cache. O redis é bem robusto, mas não é relacional, ou seja, não serve para salvar dados estruturados, do tipo uma pessoa possui 4 carros, mas sim para por exemplo fazer um sistema de ranking rápido, onde não é preciso fazer somatória disso no BD relacional e é preciso ser rápido sem seguir uma estrutura especifica.\n- O redis nasceu como banco de chave:valor : é um bd que possui somente duas colunas, a chave(KEY) podemos dizer que é o ID e o valor, que é o que quero salvar naquela coluna referente aquele ID, tipo o localstorage do navegador, que é um banco de chave:valor, ex: \"registros-dia-07: 1000\", onde a chave(ID) é \"registros-dia-07\" e o valor é \"1000\"\n- Como eu distingo os comandos do redis ? É pela primeiro letra na frente deles, por exemplo: HKEYS --\u003e tem haver com um comando de hash, Z --\u003e tem haver com um comando de ordenação, ranking S --\u003e tem haver com um comando de set, etc. [mais types de comandos](https://redis.io/docs/data-types/) [zincrby](https://redis.io/commands/zincrby/)\n- Iremos usar o comando ZINCRBY: Pois teremos uma rota na aplicação que vai listar quais foram os links mais acessados. Porque esse comando faz um incremento toda vez que tiver um acesso no member do meu set --\u003e Toda vez que tiver acesso(ZINCRBY) nesse codigo(member) é quero incrementar no redis mais um e a key é o nome do meu set/ranking\n- [zrange](https://redis.io/commands/zrange/)\n- O redis mesmo sendo um BD em memoria ele não perde as informações ao reiniciar, mas caso derrube o servidor onde ele estiver hospedado com a tua aplicação tu perde as infos. Ou seja, ele armazena em cache no servidor onde o redis e toda sua aplicação node esta rodando\n\n### Tecnologias:\n\n- Node.js\n- TypeScript\n- Fastify: Um micro framework, porque cada vez eu preciso fazer algo aqui, irei precisar instalar algo externo ou fazer algo do zero para resolver tal problema\n- Docker: O docker é basicamente uma ferramenta de conteinerização, que permite criar ambientes isolados, com suas próprias dependências, e que podem ser facilmente compartilhados e distribuídos. Podendo executar serviços, como banco de dados: MysSql, Postgres, Redis, etc. E são altamente performáticos dentro da sua maquina reaproveitando o Kernel do sistema entre eles, o que difere de uma maquina virtual, que nele é preciso instalar todo o S.O(*MUITO LENTO*), o docker possui um ambiente isolado, porem a base do seus sistema operacional(S.O) é compartilhado entre todos os ambientes.\n- PostgresSql: Ela ja faz toda parte de tratativa de SQL injection, porque ela usa essa pattern do JS que é o template string ```` sql`` ````, desde que eu não passe dessa forma ``` sql(``)``` por ele ser uma função, cada parâmetro passado é reavaliado por uma função\n- Redis\n- Zod: Validador de dados\n\n### Extensões:\n\n- Rest Client: Ela permite fazer requisições HTTP direto do VSCode, sem precisar de um cliente externo. Basta criar um arquivo na raiz do projeto: ```client.http``` tanto faz o nome, e fazer as requisições, ex:\n  ```http\n\n  # A rota para testar\n  POST  http://localhost:3000/api/links\n\n  # Informa qual é o tipo do corpo da requisição, o header\n  Content-Type: application/json\n\n  # O corpo da requisição: O request.body da rota\n  {\n    \"code\": \"react\",\n    \"originalUrl\": \"https://reactjs.org/\"\n  }\n  \n  # Separando para outra requisição\n  ###\n\n  GET  http://localhost:3000/api/links\n\n  ```\n- Eslint\n- Comment Tagged templates: Como não estamos usando nenhum ORM(Prisma e TypeOrm) para se conectar com o banco, estamos usando o proprio postgresql, quando escrevermos uma query, podemos usar essa extensão para identificar que é uma query, sem ficar parecendo um monte de string, ficando com uma sintaxe highlight, apos baixar ela, basta ir no seu codigo sql e fazer isso, ex: no arquivo *setup.ts*\n  ```sql\n  await sql /* sql */ `CREATE TABLE IF NOT EXISTS short_links`\n  ```\n- Não usei nem um ORM, pois quero aprender um pouco de sql, fazendo comandos ```Query SQL```\n\n### Caso não queira usar Docker: \n\n\u003e Todos possuem planos gratuitos\n\n- Tem o serviço de BD online do postgres: ```Neon.tech```\n- Tem o serviço de BD online do redir: ```upstash```\n\n### Comandos:\n```bash\n# Install dependências\nnpm install ou yarn\n\n# Rodar o projeto\nnpm run dev ou yarn dev\n\n# Criar base de dados postgres\nnpm run setup ou yarn setup\n\n# Rodar o docker: Esteja com o docker instalado e aberto, instale o WSL também\ndocker-compose up -d\n\n# Parar o docker:\ndocker-compose down\n\n# Para ver se tem algum erro no código:\nnpm run lint ou yarn lint\n\n# Para corrigir os erros do lint:\nnpm run lint:fix ou yarn lint:fix\n```\n\n### Ordem de comandos:\n```bash\n# Install dependências\nnpm install ou yarn\n\n# Rodar o projeto\nnpm run dev ou yarn dev\n\n# Rodar o docker: Esteja com o docker instalado e aberto, instale o WSL também\ndocker-compose up -d\n\n# Parar o docker:\ndocker-compose down\n\n# Criar base de dados postgres\nnpm run setup ou yarn setup\n```\n### Ferramentas para ver o redis rodando:\n\n- Windows: [Medis for windows](https://github.com/sinajia/medis/releases/tag/win)\n- Mac [Medir for Mac](https://getmedis.com)\n\n- Para conectar:\n```bash\nRedis Host:  localhost\nPort:  6379\nPassword: docker\n\nClick connect\n```\n\n### 👨‍💻 Autor:\n\n- Linkedin: https://www.linkedin.com/in/pedro-henrique-vieira-fernandes\n- Git: https://github.com/PedrohvFernandes\n- Instagram: pedro17fernandes\n- portfolio: https://pedrohvfernandes-web-page-portfolio.vercel.app\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedrohvfernandes%2Furl-shortening-system-with-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpedrohvfernandes%2Furl-shortening-system-with-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedrohvfernandes%2Furl-shortening-system-with-node/lists"}