npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

copacol-react-app

v2.1.0

Published

Cria um projeto novo (backend CAP + frontend web React) a partir do template Copacol

Readme

Template Copacol React — backend CAP + frontend React

Ponto de partida para um projeto novo no padrão da Copacol. É o esqueleto do Controle de Tarefas (XCOP-CONTROLE_TAREFAS_BACK / _FRONT) sem as regras de negócio de lá: fica a infraestrutura que todo projeto precisa e que já está provada em produção.

Só o template React (web): backend CAP e frontend React, sem as versões Fiori e Mobile do create-copacol-app.

| Pasta | O que é | |---|---| | XCOP_template_back/ | SAP CAP (Node.js). Postgres em dev, HANA Cloud em qas/prd. Segue docs/cap/. | | XCOP_template_front/ | React 18 + Vite 5, tema Copacol, três páginas: Home, Gestão de usuários e Configurações. | | XCOP_template_componentes/ | Os componentes padrão das páginas (hoje: a tabela de lista, a barra de filtros e o painel de indicadores) e o catálogo que mostra cada um ao vivo (npm run dev lá). O CLI copia os componentes para src/components de todo projeto. Ver Componentes padrão. |

Cada pasta vira um repositório — o CI, o deploy.sh e o .env.deploy são por repositório.

| | | |---|---| | Projeto gerado | XCOP_<nome>_back + XCOP_<nome>_front | | Onde roda | navegador (Swarm) | | Visual | tema Copacol próprio: faixa laranja institucional, Nunito + Poppins, CSS do template | | Temas (Configurações) | Copacol, os seis do Controle de Tarefas e o Noturno | | Login | keycloak-js na máquina de dev; oauth2-proxy na borda no servidor | | Ícones | lucide-react: em src/appPages.js, icon: Settings (componente) | | Página nova do CLI (o miolo é o do tipo: o cartão, a tabela, os filtros ou o painel) | src/pages/<Nome>.jsx + src/pages/Pagina.css | | Referência | XCOP_template_front/CLAUDE.md e XCOP_template_back/CLAUDE.md |

O que já vem pronto

  • Login pelo Keycloak (copacol_ad). Na máquina de desenvolvimento o SDK keycloak-js faz o login; no servidor quem autentica é o oauth2-proxy na borda, e o front só repassa o token dele. Sair encerra as duas sessões.

  • Sessão montada no backend (whoami()): identidade do Keycloak + papéis do portal de usuários + cadastro de RH do colaborador.

  • As integrações corporativas, configuradas e com fachada no backend:

    | Serviço | Variável no .env do backend | |---|---| | FileUpload | cds_requires_FileUpload_credentials_url | | Portal de usuários | cds_requires_authUsers_credentials_url | | Portal de RH | cds_requires_authEmployee_credentials_url |

    A Home mostra se cada uma responde (integrationStatus()).

    Opcionais, com fachada e linha na Home: DocuSign (/external/docusign), Termos de aceite (/external/termos_aceite) e E-mail (/external/email: o sendEmail do serviço no-reply, que envia sempre como Copacol <[email protected]>; cds_requires_email_credentials_url = https://www.copacol.com.br/<amb>/api/no-reply_email/odata/v4/app). O copacol-react-app pergunta se cada uma fica; falta só a URL no .env (ver .env.example) — sem ela, fachada e Home dizem qual variável falta (503).

    O Cofre de senhas (TI_password_vault) também é opcional — desmarcado, não entra nada dele, nem no backend (cds_requires_vault_credentials_url e cds_requires_vaultIntegration_credentials_url no .env): a credencial de cada pessoa em outros sistemas, que o app usa sem nunca ver a senha. O backend serve a API do cofre como ela é — /external/vault (o VaultService: Systems, Applications, MyCredentials com replace/validate, register, MyGrants, MyAuditEvents, com o token da pessoa) e /external/vault-integration (checkAvailability/execute, com o token de conta de serviço do Keycloak no Authorization e o JWT da pessoa no x-user-token) —, os contratos importados em srv/external/vault*.cds e, em srv/lib/cofre.js, o consumo (usarCredencial: os desfechos viram 428 VAULT_CREDENTIAL_REQUIRED com a ação quando a pessoa tem de agir) e o relay OData (<cofre>/relay/<SISTEMA>:<AMBIENTE>/<caminho> na URL de um serviço importado, com cds_requires_<Nome>_vault=true; vai com o token da pessoa e o código do app em x-vault-application, sem token de serviço). Para os dois, o app cadastrado no cofre (o código: cds_requires_vaultIntegration_credentials_application, padrão o nome do projeto); só o consumo pede o token de serviço: cds_requires_vaultIntegration_credentials_tokenUrl, _clientId e _clientSecret no .env. No front, o Cofre de senhas traz a página Minhas credenciais (menu, src/appPages.js e Gestão de usuários): cadastrar (sistema, nome, usuário e senha), conferir, trocar a senha, remover e autorizar os aplicativos a usar cada credencial — a senha vai direto ao cofre e não volta.

    E qualquer serviço OData externo, pelo $metadata dele: o copacol-react-app (ou npm run importar-servico no backend) importa com cds import e já deixa a rota /external/<Nome> funcionando — ver "Serviços externos (OData)" abaixo.

  • Deploy no Swarm: Dockerfile, stack.yml, scripts/swarm-deploy.sh, .github/workflows/ci.yaml — push em dev/qas/main publica no ambiente de mesmo nome. ./deploy.sh dev|qas|main "mensagem" faz a promoção.

  • Temas, escolhidos em Configurações: o tema Copacol (faixa laranja institucional, Nunito + Poppins), mais os seis do Controle de Tarefas e o Noturno (escuro de verdade).

  • Configurações (a página do Tarefas, sem presença): trocar e remover a foto de perfil, escolher o tema e o idioma — que valem na hora e ficam salvos no navegador.

  • Português, inglês e espanhol no app inteiro (src/i18n): texto novo na tela vai nos três dicionários.

  • Foto de perfil no FileUpload, identificada pelo NOME do arquivo: avatar-<matrícula>-<ambiente>.<ext>. A pessoa troca clicando na foto na Home; a foto do Controle de Tarefas (avatar-<matrícula>.<ext>) e a do portal de usuários também são achadas — vale a mais recente. Mostrada no topo e na Home, com as iniciais quando não há foto.

  • Menu lateral nos três modos do Tarefas: recolhido (gaveta), só ícones e fixo — a escolha fica salva no navegador.

  • Gestão de usuários (/usuarios): todo mundo que loga entra e fica registrado (primeiro e último acesso). Lá se marcam as páginas padrão (valem para todos) e se criam permissões (um nome + as páginas que libera) para dar às pessoas. As páginas vêm de uma lista única no front (src/appPages.js): página nova aparece sozinha para incluir na permissão. O admin do Keycloak abre tudo. Tabelas novas no banco: rode o npm run deploy:<perfil> do backend (o CI não faz).

Criar um projeto a partir do template

Pelo CLI, na pasta onde os projetos vão ficar:

npx copacol-react-app

Abre uma página no navegador (local, em 127.0.0.1, só nesta máquina) com as etapas: o que criar, os campos com a regra e a sugestão na hora (o que vem sugerido segue o nome até você mudar; "usar a sugestão" volta), a lista de páginas com a rota, o arquivo e o ícone de cada uma — na ordem do menu, que se muda arrastando ou pelas setas (a Home fica sempre em primeiro: é a página inicial; Gestão de usuários e Configurações mudam de lugar, mas não saem; no terminal, as novas entram logo depois da Home) —, as integrações, o resumo e, à direita, a árvore do que vai ser criado. Depois de criar, um botão sobe o backend e o front e mostra o andamento ao vivo — o npm install, "No ar" e as mensagens. O terminal fica aberto com o endereço (se o navegador não abrir, copie de lá); "Encerrar" na página, ou Ctrl+C no terminal, para tudo. --nao-abrir só mostra o endereço; --terminal faz as mesmas perguntas no terminal (o padrão em CI, por SSH e no Linux sem tela). As regras são as mesmas nos dois: a página só mostra — quem valida e gera é o bin/create.js (bin/web.js é o servidor da página, bin/web/ a página).

As perguntas: primeiro o que criar (ver abaixo), depois o nome e o título do projeto (o nome sugere as pastas XCOP_<nome>_back e XCOP_<nome>_front e todo o resto — Enter aceita; a pasta de cada projeto também pode ter outro nome: letras sem acento, números, _, - e ponto, sem espaço), DEPLOY_DIR, STACK_BASE e APP_NAME do .env.deploy de cada lado (o APP_NAME é a rota e pode ter mais de um trecho, como o senior/auth do SENIOR-Auth: o swarm-deploy.sh aceita), se quer páginas além da Home (quantas, o nome e o tipo de cada uma — Em branco (título e um cartão), Lista (tabela), que já nasce com a tabela de lista do XCOP_template_componentes, dados de exemplo e os botões funcionando, Lista com filtros, a mesma tabela com a barra de filtros em cima — texto, uma opção, várias opções e período, filtrando na hora —, ou Painel (analytics), o painel de indicadores com dados de exemplo — números, colunas por dia, barras, roscas e o mapa-múndi com o ranking de países, e o seletor de período; cada página ganha src/pages/<Nome>.jsx e uma entrada em src/appPages.js — rota, item no menu e a página na Gestão de usuários —, com ícone do lucide-react escolhido pelo nome (sem palavra conhecida, o painel fica com o de gráfico). Um nome igual ao de um componente que a página importa (Analytics, DataTable, FilterBar, KpiCard…) ou ao de um arquivo que o template já tem ganha o sufixo Pagina no arquivo e no componente: "Analytics" vira src/pages/AnalyticsPagina.jsx, com a rota /analytics), e as integrações opcionais (DocuSign, Termos de aceite, E-mail, Cofre de senhas: espaço marca, Enter confirma — a que ficar de fora sai dos dois projetos, inteira; o Cofre de senhas marcado traz também a página Minhas credenciais). Mostra o resumo, pede confirmação e cria os dois com o nome trocado em toda a tabela do passo 2: rota e título no front, API_PREFIX, namespace e CSVs, banco no .env, instância HDI no .cdsrc-private.json.example e os package.json. No fim, oferece subir os dois no mesmo terminal ([back]/[front] na frente de cada linha; Ctrl+C para os dois). A validação é inline: valor inválido não passa, e o erro diz o que corrigir. npx copacol-react-app --help resume as perguntas.

O que criar — a primeira etapa (no terminal, a primeira pergunta; ou pela flag, que já responde):

| Escolha | Flag | O que sai | |---|---|---| | Backend e front-end — o padrão | — | as duas pastas | | Só o backend | --so-backend | só XCOP_<nome>_back. Sem a etapa de páginas (elas moram no front, em src/appPages.js); das integrações opcionais, a parte do backend. "Subir" liga só ele | | Só o front-end | --so-front | só XCOP_<nome>_front. Continua pedindo o .env.deploy do backend que já existe — o APP_NAME dele dá o caminho da API (/<amb>/api/<APP_NAME>), com as mesmas sugestões e regras —, mas não cria a pasta _back; das integrações, a parte do front (a linha na Home e os textos). "Subir" liga só o front, que fala com o backend configurado (em desenvolvimento, o CAP desta máquina na 4004) |

Na página, /api/previa e /api/criar recebem isso no campo criar (ambos | back | cliente); sem o campo, ambos.

Serviços externos (OData) — no backend (some em "só o front-end"): na página, na etapa Integrações, "Adicionar metadata (.xml, .edmx)" escolhe um ou mais arquivos $metadata (OData V4 ou V2, até 5 MB cada); no terminal, a pergunta depois das integrações, ou --servico <arquivo> (repete para mais de um). O nome do serviço vem do arquivo (ddic_service.xml → ddic; genérico como metadata.xml, do namespace) e muda à vontade: só letras e números, começando por letra (o _ quebraria a variável do .env), sem repetir um serviço do template (um nome que já existe ganha um número na sugestão). Ao criar, o CLI roda no backend o npm install (o mesmo que o primeiro npm run watch faria) e o scripts/importar-servico.js dele — cds import srv/external/<Nome>.xml --as cds --force — e o projeto já sai com:

  • srv/external/<Nome>.cds (o modelo importado) e cds.requires.<Nome> no package.json, com a URL vazia: ela vem do .env de cada ambiente (cds_requires_<Nome>_credentials_url; usuário e senha técnicos, se o remoto não aceitar o token de quem está logado, em _username/_password);
  • a fachada srv/external-<nome>.cds/.js, em /external/<Nome>: o login das outras rotas (sem sessão, 401), só o que o metadata deixa (um serviço só de leitura recusa criar, alterar e excluir com 405) e a leitura — $filter, $orderby, $top, $skip, $select, $count — encaminhada ao remoto pelo cds.connect.to. Sem a URL, na máquina, a rota responde com dados de exemplo gerados do metadata (o backend sobe e a rota funciona logo depois de criado); em qas/prd, 503 dizendo a variável que falta;
  • as variáveis no .env.example (comentadas, sem valor real), a linha no CLAUDE.md do backend e os testes (test/external-<nome>.test.js, sem URL, e -remoto.test.js, com um remoto de mentira), que entram no npm test.

Num projeto que já existe, o mesmo, no backend: npm run importar-servico -- <arquivo.xml> [Nome] (ver "Serviços OData importados" no CLAUDE.md dele).

Fica na mão: cds_requires_db_credentials_password no .env, criar o .cdsrc-private.json a partir do .example, e os passos 3 a 5 abaixo.

Na mão:

  1. Copie as duas pastas do template para os repositórios novos (sem node_modules): XCOP_template_back + XCOP_template_front.

  2. Troque o nome template pelo do projeto. Todos os lugares:

    | Arquivo | Chave | Exemplo | |---|---|---| | BACK .env.deploy | DEPLOY_DIR, STACK_BASE, APP_NAME | compras/compras_service, compras, compras | | FRONT .env.deploy | DEPLOY_DIR, STACK_BASE, APP_NAME | compras/compras_app, compras, compras | | FRONT src/manifest.json | id, title, basePath, postLogoutRedirectUri, dataSources.*.uri | /compras, /api/compras/odata/v4/app/ | | FRONT vite.config.js | API_PREFIX | /api/compras | | FRONT index.html, src/brandingDefaults.js | título / APP_NAME | Compras | | FRONT index.html (script inline) | var app = 'template': o id do src/manifest.json (chaves <id>.theme / <id>.language) | var app = 'compras' | | BACK db/schema.cds, srv/app-service.cds | namespace com.copacol.template | com.copacol.compras | | BACK db/local-data/*.csv | o prefixo do nome do arquivo é o namespace | com.copacol.compras-Examples.csv | | BACK .env (a partir de .env.example) | cds_requires_db_credentials_database, _user, _password | banco do projeto | | BACK .cdsrc-private.json (a partir do .example) | instance, key do HDI | copacol-hdi-compras | | os dois package.json | name, description | |

    O namespace decide o nome físico das tabelas: troque antes do primeiro cds deploy.

  3. Apague o exemplo Examples (db/schema.cds, srv/app-service.cds, db/local-data/, listExamples em src/api/app.js) quando criar a primeira entidade real — e adapte test/memory.test.js, que faz o CRUD do modo sem banco em Examples: troque pela entidade nova, senão o npm test quebra.

  4. No servidor, crie o .env do backend em /docker-data/<dev|qas|prd>/apps/<DEPLOY_DIR>/.env — as URLs das integrações mudam de prefixo por ambiente (/appdev, /appqas, /app).

  5. No Keycloak, confira se o client de login aceita a URL do app novo (http://localhost:5173/* em desenvolvimento).

Componentes padrão — XCOP_template_componentes

Os elementos que as páginas usam, num lugar só, escritos como vão ficar no projeto (src/components). O copacol-react-app copia todos para src/components de cada projeto gerado; a página do tipo Lista (tabela) já usa a tabela de lista, a do tipo Lista com filtros, a barra de filtros em cima dela, e a do tipo Painel (analytics), o painel de indicadores.

cd XCOP_template_componentes
npm run dev        # o catálogo em http://localhost:5180 (a 1ª vez instala sozinho)
npm run build      # o catálogo estático em dist/, para publicar se quiser

O catálogo mostra cada componente ao vivo, com o CSS, os temas e os textos de verdade do template (troca tema, idioma e largura — computador, tablet, celular), mais o código do exemplo, as props e os arquivos que o CLI copia. Componente novo: ver XCOP_template_componentes/CLAUDE.md.

Hoje, três:

  • Tabela de lista (DataTable) — título com a contagem, visões, busca, atualizar/novo/copiar/excluir, marcar linhas, ordenar pelo título da coluna, escolher colunas, exportar CSV, selo de status e paginação.
  • Filtros (FilterBar) — a barra por cima da lista: campos de texto, de uma opção, de várias opções e de período; quantos estão ativos, um chip por filtro (com o x para tirar), Limpar filtros e mostrar/ocultar. Filtra ao digitar, ou só no botão Filtrar (applyOnSubmit, para o filtro que vai ao backend). A regra de cada filtro fica em filtrosLogica.js.
  • Analytics (Analytics, com as peças AnalyticsGroup, KpiCard, TrendCard, BarsCard, DonutCard e MapCard) — o painel de indicadores: a barra do período e do Atualizar, uma grade de 12 colunas (o span de cada cartão), o número grande com a variação (▲/▼), colunas por dia, barras agrupadas, roscas com o total no meio e o mapa-múndi com o ranking de países; cada gráfico tem o "Ver como tabela". Os gráficos são do recharts, nas cores do tema; o mapa vem pronto dentro do componente (mapaMundi.js, gerado uma vez no catálogo por npm run gerar-mapa), sem depender de internet. A lógica (larguras, formatos, percentuais, classes do mapa) fica em analyticsLogica.js.

E os quatro tipos de página nova do CLI: Em branco, Lista (tabela) (a tabela com dados de exemplo), Lista com filtros (a barra de filtros em cima da tabela, um campo de cada tipo, o estado na página) e Painel (analytics) (o painel com os dados de exemplo e o estado do período, pronto para trocar o exemplo pela chamada ao backend).

Publicar o CLI

A raiz é o pacote copacol-react-app (bin/create.js, mais a página do navegador em bin/web.js e bin/web/, sem dependência nova); o que ele copia são as duas pastas do template e a dos componentes (sem o node_modules do catálogo) (o files do package.json), como estão aqui.

A foto de cada tipo de página, que a página do CLI mostra na etapa Páginas, fica em bin/web/previas/: mudou um componente ou uma página de tipo, rode npm run previas antes de publicar (ver deploy_npm.md).

npm link                     # testa o comando na máquina, sem publicar
npm pack --dry-run           # confere o que vai no pacote
npm version minor            # a cada mudança no template
npm publish

O npm nunca publica .gitignore nem .npmrc. O prepack guarda cópias _gitignore/_npmrc e o CLI renomeia de volta — por isso não publique com --ignore-scripts: sem o .npmrc o build do Docker do backend quebra, e sem o .gitignore o projeto levaria node_modules e o .env para o git. O node_modules e o dist/ ficam fora do pacote pelo .gitignore.

Rodar local

# backend — copie .env.example para .env
cd XCOP_template_back
npm run watch        # http://localhost:4004 — reinicia sozinho ao salvar

# frontend
cd XCOP_template_front
npm run dev          # http://localhost:5173/template/

Na primeira vez, backend e frontend instalam as dependências sozinhos (npm install) antes de subir.

Sem Postgres: o .env.example já vem com DB_IN_MEMORY=true — o backend sobe com SQLite em memória, cria as tabelas sozinho e carrega os exemplos de db/local-data/. Os dados somem ao parar. Para usar o Postgres de dev, mude para DB_IN_MEMORY=false, preencha cds_requires_db_credentials_password e rode npm run deploy:dev uma vez para criar as tabelas.

Credenciais no .env: todas no padrão cds_requires_<serviço>_credentials_<campo>, que o CAP lê sozinho — o banco (cds_requires_db_credentials_host, _port, _database, _user, _password; em qas/prd, o HANA nos mesmos nomes, com _schema no lugar de _database), as URLs das integrações (cds_requires_FileUpload_credentials_url…) e, com o Cofre de senhas, o cofre (cds_requires_vaultIntegration_credentials_*). Senha entre aspas simples. A forma com ponto (cds.requires.db.credentials.host) e os nomes antigos (DB_*, HANA_*, VAULT_*) ainda valem.

Use localhost, não 127.0.0.1 — é o que está nos redirect URIs do Keycloak.

Regras de desenvolvimento

  • Backend: só se altera com base em docs/cap/. Projeto novo segue o livro sem os desvios de legado do Tarefas (usa ID, cuid, managed, associação gerenciada). Os únicos desvios são os da plataforma, em 08-aplicacao-neste-projeto.md.
  • Frontend: o navegador fala com um backend só; nada de URL fixa — tudo sai do manifest.json. Ver XCOP_template_front/CLAUDE.md.
  • As âncoras que o copacol-react-app troca (a tabela do passo 2 e o comentário // ↓ páginas novas entram aqui do src/appPages.js) têm de continuar nas pastas do template — se uma sumir, o CLI avisa "confira à mão".