@nectarcrm/cli
v0.2.0
Published
Nectar Dev Center CLI: local host emulator (`nectar dev`), bundle deploy (`nectar deploy`) and app sync-as-code (`nectar pull/push/diff`).
Maintainers
Readme
@nectarcrm/cli
CLI do Nectar Dev Center: login (nectar login),
criação/vínculo de app (nectar app), emulador local do host CRM (nectar dev), deploy
do bundle (nectar deploy), rollout (nectar release) e diagnóstico (nectar env).
npm create nectar-app my-app
cd my-app
npx @nectarcrm/cli devnectar dev
Sobe um harness em http://localhost:4310 com o seu app num iframe, rodando o
mesmo client.js do app-bridge que roda em produção — só o lado do host é emulado.
No harness você dispara eventos do CRM (opportunity:loaded, product:changed,
contact:saved…), lê o log bidirecional das mensagens, inspeciona sdk.storage.*,
actions, panels e toasts, e edita o AppContext do handshake. Salvou, recarrega.
| Opção | |
|---|---|
| --port <n> | porta do harness (default 4310) |
| --connect <url> | proxeia callServer para um Dev Center real (o SDK JWT é mintado localmente, o segredo nunca vai ao browser) |
| --open | abre o harness no browser |
Por padrão o emulador é offline: callServer/http respondem de fixtures/.
nectar login — sessão por Dev Center
nectar login # developer.nectarcrm.com.br
nectar login --host http://localhost:2337
nectar login --env qa2 # pelo nome de um ambiente já no config
nectar whoami --env qa2
nectar logout --env qa2Device flow (RFC 8628): o terminal mostra um código curto, você aprova em /device
no browser — onde a sessão já existe. Funciona por SSH e em container (--no-browser
imprime a URL em vez de abrir).
local, qa2 e produção são instalações diferentes, com contas diferentes: a sessão
é guardada por host em ~/.nectar/config.json (modo 600), fora do projeto. Isso é o
oposto da API key, que é por app e mora no .env do projeto.
nectar app — criar ou vincular
nectar app list --env qa2 # seus apps naquele Dev Center
nectar app create "Meu App" --env qa2 # cria lá, emite a API key e configura aqui
nectar app link --env qa2 # vincula a um app existente (idem)Os dois últimos gravam o ambiente no nectar.config.json e a key no .env — ou seja,
substituem o preenchimento manual. Como o appId muda por Dev Center, rode uma vez por
ambiente.
O link sugere o app cujo slug bate com os outros ambientes, mas sempre pede
confirmação: o slug é único por host (uma colisão vira nome-2), então casar por ele é
palpite. Quem define o vínculo é o environments do seu config.
nectar add — setup de um ambiente sem login
nectar add # pergunta host, app id e API key; repita para cada ambienteConfere as três coisas contra o Dev Center antes de gravar (é o momento mais barato de
descobrir que a key é de outro app) e escreve cada uma no lugar certo: host e appId no
nectar.config.json, a key no .env. A key não aparece na tela enquanto você digita.
Sem TTY (CI), aceita --env/--host/--app-id e falha se a credencial não conferir.
Ambientes
deploy e release recebem --env <nome>, resolvido no nectar.config.json:
{
"environments": {
"qa2": { "devCenterUrl": "https://devcenter-qa2.nectarcrm.com.br", "appId": "<uuid no qa2>" },
"prod": { "devCenterUrl": "https://developer.nectarcrm.com.br", "appId": "<uuid em prod>" }
},
"defaultEnv": "qa2"
}Cada ambiente é um Dev Center diferente, então o appId muda em cada um — por isso
fica no config, versionado. Com 2+ ambientes e sem defaultEnv, --env é obrigatório:
publicar no alvo errado seria silencioso.
Cada campo resolve por flag > NECTAR_*_<ENV> > NECTAR_* > config:
| Campo | Flag | Env var do ambiente | Env var genérica | Config |
|---|---|---|---|---|
| host | --host | NECTAR_DEVCENTER_URL_PROD | NECTAR_DEVCENTER_URL | environments.prod.devCenterUrl |
| appId | --app-id | NECTAR_APP_ID_PROD | NECTAR_APP_ID | environments.prod.appId |
| key | — | NECTAR_API_KEY_PROD | NECTAR_API_KEY | — |
A env var do ambiente vence a genérica: exportar uma no shell não redireciona os deploys dos outros. Dá para rodar em CI sem config nenhum (só env vars) ou local sem env var nenhuma (só config).
A key nunca vem do config nem de flag — em linha de comando vazaria no histórico do
shell e no ps. Só env var ou arquivo: o CLI lê .env e, com --env qa2, também o
.env.qa2 por cima.
nectar env --env prod # host, appId e key mascarada — com a origem de cada um
nectar env --all # todos os ambientes lado a lado (o mesmo app em cada Dev Center) qa2 (default) ec706c71-9ac1-4f87-8a6a-00823a296c6e ✔
https://devcenter-qa2.nectarcrm.com.br
local 3ef1a8ec-ea54-4739-8af4-ed9426165d65 ✖ NECTAR_API_KEY_LOCAL
http://localhost:2337
prod 0d8f455f-16a0-403c-b7b9-35ce15c3fab4 ✔
https://developer.nectarcrm.com.brnectar deploy
nectar deploy --env qa2 --dry-run # lista o que subiria
nectar deploy --env qa2 # sobe pro draft
nectar deploy --env qa2 --publish # congela o bundle como nova versãoSobe os arquivos de primeiro nível do bundle, pulando *.test.js, *.spec.js,
fixtures/, nectar.config.json e qualquer .env*. A API key (escopada a 1 app) sai de
Configuration → API Keys do ambiente.
nectar release — publicar ≠ estar no ar
Se o app já tem uma release ativa, é ela — não o bundle marcado como ativo — que
decide o que os tenants recebem. Nesse caso deploy --publish congela o bundle e o
código não vai ao ar; o CLI avisa. Quem libera é:
nectar release --env prod --changelog "corrige arredondamento"O release congela um snapshot do app (functions, inbound, outbound e o bundle atual) e
o promove a ativo — rollout global no ambiente, para todos os tenants. Apps sem
nenhuma release são servidos direto do bundle ativo, e aí --publish basta.
Sync-as-code — pull, push e diff
O deploy/release cuidam do bundle. O backend do app — functions, connectors,
settings, custom fields, env vars, inbound e outbound — vai e volta por aqui, com o git
como fonte de verdade:
nectar pull --env qa2 # instância → repo
nectar diff --env qa2 # o que um push mudaria (não escreve nada)
nectar push --env qa2 --dry-run # calcula o resultado sem persistir
nectar push --env qa2 # aplicaO pull explode o app em arquivos que dão diff legível:
app.json metadados do app
functions/<nome>.js código da function
functions/<nome>.json meta (events, cron, flags, timeouts)
connectors.json settings.json custom-field-templates.json
env-schema.json inbound.json outbound.json environments.jsonO push faz upsert por chave natural (function por nome, custom field por
tabela+alias, setting por key): o app não é recriado e IDs/API keys são preservados. Dá
para editar ao vivo no Dev Center e trazer para o repo depois, sem conflito.
Remoções não são silenciosas
O sync do dev-center apaga em alguns recursos e não apaga em outros:
| Recurso | O que existe no destino e não no repo |
|---|---|
| inboundEndpoints, outboundRules, envVars | é removido |
| functions, connectors, customFieldTemplates, settingTemplates | é mantido |
Antes de aplicar, o push roda o mesmo endpoint em modo dry-run — as contagens vêm do
código que rodaria de verdade, então detectar remoção não depende da tabela acima. Se
algum item sumiria, ele para e lista o que é, exigindo --yes. E a garantia não é só
do cliente: sem --yes o push envia allowRemovals=false, e é o servidor que recusa
apagar, devolvendo o que manteve.
✖ This push would REMOVE 1 item(s) on 'prod':
- envVars: SX_USUARIO_REGULARIZACAO
Re-run with --yes to apply, or `nectar pull` first to bring them in.Migração entre ambientes
pull de um ambiente e diff contra o outro: zero diferenças significa que a migração
foi fiel. Em CI, --exit-code faz o diff sair com 1 quando há qualquer diferença.
nectar pull --env qa2 --app apps/sx
nectar diff --env prod --app apps/sx --exit-codeSegredos nunca viajam
Env vars secretas e credenciais de connector não são exportadas — voltam como
placeholder {{VAR}}. pull e diff listam quais precisam ser preenchidas no destino;
um app migrado sem esse passo sobe e só quebra em runtime.
O bundle não entra no pull/push (tem deploy/release), e environments e
testConfig ainda não são aplicados pelo sync — o CLI avisa quando aparecem no diff.
Referência completa: https://developer.nectarcrm.com.br/docs/cli Passo a passo: https://developer.nectarcrm.com.br/docs/testing-locally
