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

@nomad-e/gaudi-cli

v3.0.0

Published

CLI para consumir a API Gaudencio-Cloud (workloads, volumes, tenants, containers)

Readme

gaudi-cli

CLI em Node.js para consumir a API Gaudencio-Cloud (workloads, volumes, tenants).

Instalação

cd cli
npm install
npm link          # opcional: cria o comando global `gaudi-cli`

Sem npm link, executa com node bin/gaudi-cli.js.

Configuração

A config é persistida em ~/.gaudi-cli/config.json (permissões 0600).

  • Base URL da API: por omissão https://gaudi-v2-api.factorai.cloud/api/v1 (instância de produção). Define com a env GAUDI_API_URL ou edita o ficheiro de config.
  • ERP Middleware: por omissão https://erp-middleware.factorai.cloud. Define com a env ERP_MIDDLEWARE_URL.
  • Token / tenant: guardados automaticamente após auth login (o login sincroniza o tenant internamente).

Fluxo rápido

# 1. Autenticar (interativo: pede factorai_domain, username e password)
#    Resolve erp_url/erp_db via ERP Middleware e sincroniza o tenant automaticamente.
gaudi-cli auth login

# 2. Listar o catálogo de imagens AI-native
gaudi-cli workload-type list

# 3. Criar e fazer deploy de um workload
gaudi-cli workload create -n "Documentos" -w 1
gaudi-cli workload deploy -i <id>
gaudi-cli workload status -i <id>
gaudi-cli workload logs -i <id>

Comandos

auth

| Comando | Descrição | |---------|-----------| | auth login [--factorai-domain <d>] [-u <user>] [-p <pass>] | Autentica de forma interativa (3 dados) e sincroniza o tenant automaticamente | | auth me | Mostra o utilizador autenticado | | auth renew | Renova o access token usando o refresh token guardado (POST /auth/refresh) | | auth logout | Revoga a sessão e limpa a config local | | auth status | Mostra o estado da sessão local (sem chamar a API) |

O auth login pede apenas factorai_domain, username e password. Os detalhes ERP (erp_url, erp_dbname) são resolvidos automaticamente a partir do factorai_domain via ERP Middleware (companies/me?domain=<d>), e o tenant é sincronizado internamente — o utilizador final não precisa de invocar o sync.

workload-type (catálogo de imagens AI-native)

| Comando | Descrição | |---------|-----------| | workload-type list [--show-inactive] | Lista o catálogo | | workload-type create -k <key> -n <name> --image <img> [...] | Regista um tipo | | workload-type get -i <id> | Mostra um tipo | | workload-type update -i <id> [...] | Atualiza um tipo | | workload-type delete -i <id> | Remove um tipo |

workload (instâncias por tenant)

| Comando | Descrição | |---------|-----------| | workload list [-t <tenant>] | Lista os workloads de um tenant | | workload create -n <name> -w <type_id> [-t <tenant>] | Cria um workload (sem deploy) | | workload get -i <id> [-t <tenant>] | Mostra um workload | | workload update -i <id> [-t <tenant>] [...] | Atualiza um workload | | workload delete -i <id> [-t <tenant>] | Remove um workload | | workload deploy -i <id> [-t <tenant>] [--cpu <c>] [--mem <m>] [--volume-id <v> --volume-mount-path <p>] | Deploy on-demand do container | | workload publish -i <id> [-t <tenant>] | Publica explicitamente o mapeamento de roteamento dinâmico (app-{slug}.{domain}) | | workload stop -i <id> [-t <tenant>] | Para o container | | workload status -i <id> [-t <tenant>] | Consulta o status | | workload ports -i <id> [-t <tenant>] | Lista as portas expostas | | workload logs -i <id> [-t <tenant>] [--tail <n>] | Mostra os logs | | workload logs-stream -i <id> [-t <tenant>] [--tail <n>] [--raw] | Stream contínuo (SSE) dos logs em tempo real | | workload attach -l <label> -c <container_id> [-t <tenant>] | Anexa um container Docker nativo | | workload copy-file -i <id> --path <dir> --file <local> [--filename <name>] [-t <tenant>] | Copia um ficheiro local para dentro do container | | workload copy-dir -i <id> --path <dir> --dir <local> [-t <tenant>] | Copia um diretório local (recursivo) para dentro do container | | workload exec -i <id> -c <cmd> [-t <tenant>] [--workdir <dir>] [--user <u>] [--timeout <s>] | Executa um comando dentro do container |

volume (armazenamento Docker por tenant)

| Comando | Descrição | |---------|-----------| | volume list [-t <tenant>] | Lista os volumes | | volume create -n <name> [-t <tenant>] | Cria um volume persistente | | volume get -i <id> [-t <tenant>] | Mostra um volume | | volume update -i <id> [-t <tenant>] [...] | Atualiza um volume | | volume delete -i <id> [-t <tenant>] | Remove um volume |

daemon (renovação automática de token)

| Comando | Descrição | |---------|-----------| | daemon start | Inicia o daemon em background (processo orphan) que renova o token automaticamente antes de expirar | | daemon stop | Para o daemon de renovação de token | | daemon status | Mostra o estado do daemon (a correr / PID) |

O daemon é um processo orphan (detached) que sobrevive ao fim de cada invocação do CLI. Mantém a sessão viva renovando o access token a 50% do seu tempo de vida, usando o refresh token guardado. Inicia automaticamente após o auth login — não é preciso correr daemon start manualmente. O auth logout para o daemon automaticamente. O PID é guardado em ~/.gaudi-cli/daemon.pid para evitar duplicados.

Renovação de token (engenharia)

O gaudi-cli mantém a sessão viva renovando o access token antes de expirar, de duas formas complementares:

  • Manualauth renew faz POST /auth/refresh com o refresh token guardado e persiste os novos tokens/sessão.
  • Automática — o daemon (processo orphan/detached) renova o token a 50% do tempo de vida do access token atual, sem precisar de o CLI estar a ser usado.

Como funciona:

  1. No auth login (e no auth renew), o CLI grava tokenIssuedAt e tokenExpiresAt (epoch ms) na config, calculados a partir do expires_in devolvido pela API.
  2. O daemon lê esses timestamps e calcula o ponto de renovação: issuedAt + (expiresAt - issuedAt) × 0.5. Quando esse momento chega, faz POST /auth/refresh e atualiza a config com os novos tokens e timestamps.
  3. Se os timestamps não existirem (config antiga), o daemon renova a cada 60s como fallback.
  4. O daemon é gerido por um ficheiro PID (~/.gaudi-cli/daemon.pid) para evitar duplicados — daemon start não lança um segundo processo se já houver um a correr.
  5. Inicia automaticamente após o auth login — não é preciso correr daemon start manualmente. O daemon start/stop/status existem para gestão manual (ex: parar o daemon).
  6. O auth logout para o daemon automaticamente.

Multiplataforma: o spawn usa detached: true + windowsHide: true (no Windows, detached abriria uma janela de console nova — é escondida). O daemon limpa o PID file de forma graciosa ao receber SIGTERM/SIGINT no Unix; no Windows o daemon stop remove o PID file antes de terminar o processo.

Opções globais

  • --json — saída em JSON puro (máquina/IA)
  • -h, --help — ajuda de qualquer comando
  • -t, --tenant <id> — ID do tenant (default: o guardado pelo auth login)

Testes

A suíte usa o runner nativo do Node (node:test) — sem dependências extra.

cd cli
npm test

Cobre:

  • Unit (test/api.test.js, test/config.test.js, test/output.test.js) — cliente HTTP (com fetch mockado), persistência de config e formatação de output.
  • Integração (test/cli.integration.test.js) — sobe um servidor HTTP local que imita a API e executa o CLI como subprocesso, verificando parsing de comandos, consumo da API e output.

Notas

  • Tenant: o tenant_id é resolvido por omissão a partir da config (após auth login). Pode ser sobrescrito com -t <id> em qualquer comando de tenant-scoped. Os comandos workload e volume são scoped por tenant.
  • Gestão de tenants: não há comandos tenant expostos no CLI — o tenant é sincronizado automaticamente pelo auth login (via ERP Middleware). O módulo src/tenant.js existe no código com CRUD completo (tenant list/create/get/update/delete), mas não está registado no bin/gaudi-cli.js (comentado). Se for necessário expor a gestão de tenants, basta registar registerTenant(program).
  • Renovação de token: o CLI renova o access token manualmente (auth renew) e automaticamente (daemon start), gravando tokenIssuedAt/tokenExpiresAt na config. Ver a secção "Renovação de token (engenharia)".
  • O comando container foi removido — a gestão de containers é feita através de workload.