Cada ferramenta, num só sítio
Esta página é a referência prática para cada ferramenta da barra lateral do seu ambiente Archestack. Cada secção cobre o que a ferramenta faz, quando recorrer a ela, os passos para os fluxos de trabalho mais comuns e as armadilhas que apanham os utilizadores novos. A secção final (APIs invocáveis a partir de scripts) documenta a superfície exata que os scripts podem chamar.
Schema Designer
Um editor visual para o schema da base de dados, tabelas, colunas, tipos, relações, índices, que guarda automaticamente num documento JSON. O schema é a fonte da verdade para a sua aplicação; nenhuma outra ferramenta vê uma coluna enquanto não a adicionar aqui e fizer deploy.
Fluxo comum: na barra de ferramentas, clique em Add Table (botão de
ícone). Abre-se um diálogo intitulado "Create New Table"; escreva um nome (o texto de ajuda
lembra "Lowercase with underscores recommended"), clique em Create. A tabela aparece
no canvas com uma chave primária SERIAL id gerada automaticamente. Selecione a
tabela e o painel à direita abre no separador Columns. Adicione colunas a partir da
caixa com contorno tracejado "Add column" em baixo (campo de nome, menu Type, clique em
Add Column). Clique em cada coluna para expandir e ajustar os toggles (PK,
NULL, UQ), Length e Default value.
Tipos de coluna disponíveis no menu Type: SERIAL, BIGSERIAL, INTEGER, BIGINT, SMALLINT, DECIMAL, NUMERIC, REAL, DOUBLE PRECISION, VARCHAR, CHAR, TEXT, BOOLEAN, DATE, TIME, TIMESTAMP, TIMESTAMPTZ, UUID, JSON, JSONB, BYTEA, INET, CIDR, MACADDR, MONEY, INTERVAL, mais tipos geométricos e de array. Length só é relevante para VARCHAR e CHAR.
As chaves estrangeiras vivem no separador Relations do painel à direita (não "Relationships"). Desça até "Add relationship": escolha a coluna FK na tabela atual, o tipo de relação (One-to-One / One-to-Many / Many-to-Many), a tabela de referência, a coluna de referência e clique em Add Relationship. Cada relação tem menus pendentes On Delete e On Update (CASCADE / SET NULL / SET DEFAULT / RESTRICT / NO ACTION).
Auto-save: o indicador no canto inferior esquerdo alterna entre "Auto saving…" e "Saved". Há também um botão Save na barra de ferramentas (só ativado quando há alterações pendentes) para guardar explicitamente.
Outros botões da barra de ferramentas: Add Group (contentores visuais para tabelas relacionadas, painel de propriedades intitulado "Group"), Add Text (anotações em forma livre, painel de propriedades intitulado "Text Annotation"), controlos de zoom, filtro de package e pesquisa de tabela.
Armadilhas: renomear uma coluna produz um plano destrutivo (drop + add),
edite o SQL no separador Generated SQL do deployment para usar RENAME COLUMN se
quiser preservar os dados. Adicionar uma coluna NOT NULL a uma tabela não vazia sem default
falha, torne-a nullable, faça backfill, e só depois altere. O botão Deploy da barra
de ferramentas leva-o a uma página de configuração de deployment, não diretamente para um
deploy.
Database Deployments
Lista cada deployment com o seu estado (Draft / Executing / Succeeded / Failed) e corre
novos. Rota: /database-deployments/overview.
Botões no canto superior direito: Refresh (recarrega a lista), New Deployment (cria um novo rascunho).
A partir do Schema Designer: o botão verde Deploy com ícone de
foguetão na barra de ferramentas do Schema Designer leva-o a
/database-deployments/configure/new, uma página de configuração de deployment
nova.
Página de configuração de deployment: dois separadores.
- Configuration - editores de scripts pre/post-deployment (PostgreSQL) com um botão Test Run em cada. O pre-script corre antes das alterações de schema; o post-script corre depois. Útil para backfills, reconstruções de índices ou limpezas de áreas de staging. Mais um toggle Force Deploy (Allow Data Loss) para operações destrutivas.
- Generated SQL - mostra a migração que a plataforma produziu. O SQL é editável. Um botão Regenerate (ícone de refresh) corre o diff outra vez se tiver feito alterações de schema desde que abriu esta página.
Botões no topo: Back, Save (guarda a configuração como Draft), Deploy (corre o deployment imediatamente). O Deploy é o último que clica.
Armadilhas: os deployments não são automaticamente envolvidos numa
transação, uma falha a meio deixa a base de dados num estado parcial. Para migrações
arriscadas, envolva os seus statements em BEGIN; … COMMIT; no pre-script. O
toggle Force Deploy salta as verificações de segurança; use-o de forma deliberada.
Business Entities
Vistas curadas construídas sobre uma master table mais joins de tabelas relacionadas. As páginas ligam-se a Business Entities, nunca a tabelas em bruto. Ver Conceitos → Business Entities para perceber o porquê.
Fluxo comum: clique em Create. Abre-se o editor em página inteira com os separadores Visual, JSON, Events. Defina Entity Name, Master Table (Autocomplete) e Label Column (a coluna cujo valor representa um registo em seletores). Guarde, a BE gera automaticamente uma lista de colunas nativas a partir da master table.
Adicionar joins: desça até ao cartão Join Configurator e clique em Add Join. Cada join abre como um Accordion com: Join Type (INNER / LEFT / RIGHT), From Table, To Table (Autocomplete agrupado por Database Tables / Third Party), From Column, To Column, menus opcionais Type Cast, e um seletor de colunas para indicar que colunas alvo expor.
Agregações: num join, ative Aggregate Mode. Para cada coluna escolhida escolhe depois uma Aggregate Function: COUNT / SUM / AVG / MIN / MAX / COUNT DISTINCT. "Número de contactos em aberto desta empresa" é o exemplo canónico.
Run Preview: o editor tem um botão Run Preview (com um ícone de play) que executa a configuração de joins completa e mostra linhas reais numa grelha de dados. Se uma coluna de join vier vazia, a coluna não foi marcada no seletor de colunas do join (ou a relação está mal configurada).
Várias BEs por master table: nada o impede de ter
customer (sales view) e customer (support view) sobre a mesma
master. Páginas diferentes, colunas adequadas ao público, a mesma linha subjacente.
Armadilhas: as colunas juntadas e agregadas são só de leitura. Para editar a etiqueta juntada, navegue até ao registo de origem. As colunas agregadas são recalculadas em cada query, ok para centenas de linhas, lento em milhões.
Page Editor
Configura a UI em runtime ligando uma Page a uma Business Entity. A plataforma gera automaticamente secções com base nas colunas da BE; afina a disposição a partir daí. Não há um "seletor de templates" separado, cada página parte da mesma baseline gerada e personaliza-a.
Fluxo comum: clique em Create. Preencha Page Name,
Page Route (por exemplo /companies), escolha a Business Entity
(Autocomplete). A página abre no editor com os separadores Visual, Overview,
Create, Entities, Events, JSON. Ajuste a disposição gerada
automaticamente, depois vire o interruptor Published no cabeçalho do topo para ON.
Tipos de widget de campo (o Select Type em cada campo): Text,
Textarea, Number, Date, Select, Checkbox, Email. Use Select para campos de chave
estrangeira e defina o autocomplete Entity do campo para a BE referenciada para que os
utilizadores escolham por etiqueta.
Separadores no formulário de detalhe: clique em Add Tab no separador
Visual. Dentro de um separador pode adicionar uma secção RelatedGrid ligada a outra BE
filtrada pela PK do registo atual. Exemplo clássico: uma página Company com separadores
"Contacts" e "Deals", cada um filtrado por company_id = id da empresa atual.
Botões de ação no Header inspector do formulário de detalhe. Clique em Add na secção Actions. Cada ação tem Label, Icon (Save / Delete / Add / Refresh / Download / Bolt / None), Variant (Contained / Outlined / Text), Color (Primary / Secondary / Error / Success / Warning / Info) e Steps (uma lista ordenada de: Save Record, Delete Record, Navigate, Business Events, Custom). Para correr um Business Event a partir de um botão, defina o tipo do passo como Business Events e escolha o evento pelo nome.
Publicação: o interruptor Published no cabeçalho do topo é o único controlo de publicação. ON = a página aparece em Published Pages na barra lateral e os utilizadores finais que naveguem para a sua rota veem-na. OFF = rascunho (só você no editor vê as suas alterações).
Armadilhas: as colunas geradas automaticamente numa Page nova espelham a BE, se a BE mudar (adiciona um join), a Page não vai apanhar as novas colunas. Recarregue a página no editor ou adicione a coluna manualmente à secção. Atualmente não existe um tipo de passo de ação "Generate PDF", para ligar um PDF a um botão de página, exponha o PDF via um Script Module que chama o endpoint REST e use um passo Custom (ou chame o endpoint diretamente a partir de um Frontend Template).
Business Events
Regras que disparam em alterações de dados (ou num horário, ou manualmente) e correm ações quando as condições são satisfeitas. O mecanismo "quando X acontece, faz Y" da plataforma. Ver Conceitos → Business Events para o modelo.
Fluxo comum: clique em Create. Defina Rule Name, ative Enabled. Escolha Business Entity. Marque um ou mais Triggers: BeforeCreate / BeforeUpdate / AfterCreate / AfterUpdate / BeforeDelete / OnSchedule / Manual / InitialValue. Construa a árvore de condições (grupos AND/OR). Adicione uma ou mais ações no FlowCanvas. Guarde.
Tipos de ação (RuleActionKind):
- Execute Script - corre um script C#. A ação mais flexível; recorra a ela sempre que quiser definir um campo, fazer um cálculo, chamar uma API, qualquer coisa personalizada. O script recebe
Entity(mute-o em triggers Before* para alterar a escrita em curso),OldEntity,Log,Db,Modules. - Validate - um script que devolve
bool.truesignifica que a validação falha e a gravação é bloqueada com a mensagem de erro configurada. Opcionalmente destaca colunas específicas via errorColumns. - Block Operation - bloqueia duramente a operação com uma mensagem configurada. Sem script.
- Create Entity - insere um registo noutra BE. Os valores dos campos suportam expressões de template como
{{ Entity.column_name }}e{{ now() }}. - Update Entity - atualiza registos noutra BE que correspondam a um filtro de condição. Mesmas expressões de template.
- Delete Entity - apaga registos que correspondam a uma condição. Recusa disparar sem uma condição (segurança).
- Send Email / Send Webhook / Publish Event - definidos no schema como melhorias futuras; atualmente são registados e ignorados.
Padrão "definir um campo": não existe uma ação discreta Set Field. A
forma de definir um campo é um Execute Script num trigger Before* que muta
Entity. Exemplo: Entity.title = ((string)Entity.title)?.Trim();. A plataforma
persiste o Entity modificado como parte da escrita em curso, sem query extra, sem risco de
recursão.
Run Simulation: o separador Simulate do editor de trigger tem um seletor de registo e um botão Run Simulation. A plataforma corre as suas condições e ações contra o registo escolhido sem persistir alterações, as operações de escrita executam dentro de uma transação que é revertida. O painel de output mostra que condições corresponderam e o que cada ação teria feito. Use isto para apanhar configurações erradas antes de dados ao vivo lhes baterem.
Expressões de template na configuração de ações usam chavetas
{{ … }}. Os tokens reais: {{ Entity.column }},
{{ OldEntity.column }},
{{ now() }} / {{ getdate() }}, {{ today() }},
{{ guid() }} / {{ newid() }}, {{ year() }},
{{ month() }}, {{ day() }}, {{ timestamp() }},
agregações como {{ SUM(column) }} dentro de contextos de join, e aritmética
pós-substituição como {{ Entity.quantity * Entity.price }}.
Não existe um token {{ user.email }}.
Operadores de condição: Equals, NotEquals, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual, Like (= ILIKE), Contains (= ILIKE %value%), IsNull, IsNotNull, In (= ANY(...)).
Armadilhas: um trigger que muta o mesmo registo que vigia volta a disparar-se
se usar Update Entity; use antes Before Update + Execute Script
+ Entity.field = …. Dois triggers no mesmo evento disparam por ordem de
prioridade. Eventos desativados continuam a aparecer na lista, o toggle Enabled é
separado da configuração do trigger.
Script Modules
Scripts C# reutilizáveis compilados em runtime pelo Roslyn. Recebem parâmetros, consultam a
base de dados via o helper Db, devolvem um valor. Invocáveis a partir de Business
Events, Scheduled Events e diretamente do front-end.
Fluxo comum: clique em Create. Abre-se o editor com os separadores
Edit, Parameters, Test, JSON. Dê um nome ao módulo
(PascalCase, por exemplo RecalcOpenRevenue). No separador Parameters,
clique em Add por parâmetro (Name, Type, Required, Default Value). Opções de Type:
string, int, decimal, double, bool, DateTime. De volta ao separador Edit, escreva C#.
O IntelliSense está ligado.
Painel Test: o separador Test mostra os inputs de parâmetros à esquerda e um botão Run (ícone PlayArrow). Clique em Run; o lado direito mostra um indicador de sucesso ou erro, log de output e o valor de retorno (formatado em JSON).
O helper Db, ver a referência completa em APIs invocáveis a partir de scripts abaixo.
Chamar a partir de um Business Event: adicione uma ação Execute Script cujo corpo chame o módulo:
await Modules.CallAsync("RecalcCompanyOpenDealValue", new Dictionary<string, object?> {
["company_id"] = Entity.company_id
}); Chamar a partir de um Scheduled Event: crie um evento com o trigger
On Schedule, defina o cron, adicione uma ação Execute Script com o mesmo
corpo Modules.CallAsync.
Logging: cada invocação escreve uma entrada em Event Logs com tempo de execução, parâmetros e resultado (ou erro).
Armadilhas: faça sempre await nas chamadas Db, esquecer compila
mas devolve um Task. Os returns passam por objeto (não são serializados em JSON pela
framework); para consumo no front-end, devolva objetos anónimos com campos primitivos.
Suggestion-on-commit-character está intencionalmente desativado no editor; use Tab para
aceitar.
Frontend Templates
Fragmentos de UI reutilizáveis escritos em TSX que o editor de páginas pode largar numa página. Útil quando os templates configurados não chegam, gráficos à medida, disposições invulgares, integrações de widgets de terceiros.
Fluxo comum: clique em Create, dê um nome ao template, escreva um
componente TSX no editor. O componente recebe props: record (a linha atual quando
embutido num formulário de detalhe), refresh (refazer fetch dos dados) e alguns
helpers. Guarde. Referencie o template a partir de um campo do Page Editor.
Empacotável: os templates fluem pelo sistema de Package como qualquer outro objeto de configuração, são trazidos em cascata quando uma página que os usa é adicionada a um package.
Armadilhas: o TSX está em sandbox, não pode importar pacotes npm arbitrários. Cinja-se ao React + aos helpers fornecidos.
PDF Templates
HTML + template Scriban + um pequeno data script C# que renderiza para PDF (Chromium headless). Cada template é invocável pelo nome a partir de um script via REST ou diretamente a partir de um botão numa Page (com um pequeno adaptador, ver abaixo).
Fluxo comum: clique em + Create. O editor abre com campos de texto Name e Description no topo, cinco separadores do lado esquerdo (HTML Template, Data Script, Settings, Params, JSON), e um painel PDF Preview sempre ligado à direita. Os separadores Data Script e HTML Template abrem cada um um editor Monaco na metade esquerda; a pré-visualização re-renderiza quando guarda (botão verde Update no canto superior direito).
Declare parâmetros no separador Params via o botão + Add (Name, Type, Required, Default Value). A etiqueta do separador atualiza para Params (n) com a contagem. Formato de página / orientação / margens / escala / cabeçalho / rodapé vivem no separador Settings.
Forma do data script (ver tutorial PDF Invoices para um real):
var deal = await Db.GetAsync("deal", deal_id);
var lines = await Db.From("deal_line")
.Where("deal_id", "=", deal_id).ToListAsync();
return new {
InvoiceNumber = $"INV-{deal.id:D6}",
Lines = lines.Select(l => new { l.description, l.quantity })
}; Forma do template HTML (Scriban, semelhante a Liquid/Handlebars):
<h1>{{ InvoiceNumber }}</h1>
<table>
{{ for line in Lines }}
<tr><td>{{ line.description }}</td><td>{{ line.quantity }}</td></tr>
{{ end }}
</table> Painel de pré-visualização: sempre visível do lado direito do editor. Re-renderiza quando guarda (botão verde Update). Inclui uma coluna de thumbnails para PDFs multi-página e uma barra de ferramentas de visualizador integrada (zoom, rotação, download, imprimir). Os botões de ícone no canto superior direito do editor alternam a visibilidade do painel de pré-visualização e a edição em ecrã inteiro.
Chamá-lo a partir de fora do editor:
POST /api/v1/pdf-templates/{id}/preview- renderiza por ID, devolveapplication/pdf. Usado pelo painel de pré-visualização do editor.POST /api/v1/pdf-templates/generate/{name}- renderiza por nome, devolveapplication/pdf.POST /api/v1/pdf-templates/generate/{name}/base64- igual mas devolve{ "data": "<base64>" }.
Passe os valores dos parâmetros no body JSON. Auth é o token Bearer padrão.
Limitação de trial: tanto o endpoint generate como o endpoint
{id}/preview (usado pelo painel de pré-visualização do editor) devolvem
403 em modo trial, a renderização de PDF está totalmente bloqueada. Pode continuar a autorar o
template (data script, HTML, definições, parâmetros) e guardá-lo; só não verá um PDF
renderizado até estar num ambiente pago.
Nota sobre renderização invocável por script: o contexto de scripting C#
não expõe um global Pdf. Para renderizar um PDF a partir de um Script
Module hoje, chame o endpoint REST generate via HttpClient. (O
autocomplete do editor de script anuncia Pdf.RenderAsync para compatibilidade
futura; o binding em runtime ainda não está ligado.)
Armadilhas: Scriban escapa HTML por defeito. Quebras de página são por CSS,
page-break-before: always numa secção. As fontes disponíveis no servidor de
renderização estão limitadas a fontes do sistema mais as famílias Noto e Liberation, embuta
a sua própria via base64 @font-face se precisar de uma fonte de marca.
Scheduled Events
O mesmo sistema de Event Trigger que Business Events, com o trigger On Schedule marcado. Use-o para recálculos noturnos, resumos semanais, limpezas periódicas, relatórios mensais.
Fluxo comum: crie um Business Event com o trigger On Schedule (em vez
de, ou em adição aos, triggers de alteração de dados). Configure a expressão cron. Adicione uma
ação Execute Script cujo corpo invoque um Script Module via
Modules.CallAsync(...).
Expressões cron: 6 ou 7 campos no estilo Quartz, ver Conceitos → Scheduled Events para padrões comuns. As horas são hora do servidor (UTC no stack de produção).
Armadilhas: um job de longa duração que ultrapassa o seu intervalo cron não duplica, o Quartz não dispara uma segunda instância do mesmo job em simultâneo, o segundo tick é saltado. Execuções falhadas não tentam de novo automaticamente; construa o retry no script.
Packages
Bundles exportáveis de objetos de configuração (BEs, páginas, eventos, scripts, templates, schema) com dependências em cascata. Adicionar uma Page a um package traz automaticamente tudo o que essa página referencia.
Fluxo comum (export): clique em Create, nomeie e versione o package. Adicione os objetos de topo que lhe interessam, geralmente um punhado de páginas. Abra o painel de linked-items para ver a lista em cascata (o que o package vai realmente conter). Desmarque qualquer coisa que queira omitir. Decida se quer incluir dados (toggle na exportação). Clique em Export, obtém um ZIP.
Fluxo comum (import): no ambiente de destino, abra Packages, clique em Import, faça upload do ZIP. A plataforma mostra o que vai ser adicionado ou atualizado. Deltas de schema não são auto-aplicados, se o package referencia uma coluna que não existe no destino, a importação falha.
Armadilhas: os identificadores são por nome, não por ID numérico. Uma BE chamada "customer" na origem liga-se a uma BE chamada "customer" no destino, renomeie de qualquer lado e a ligação parte.
Third-Party Data Connections
Ligações a bases de dados externas (Postgres, SQL Server, MySQL, outras) que importam tabelas num horário. As tabelas importadas comportam-se como tabelas nativas, aparecem no Schema Designer e podem ser referenciadas por Business Entities, Pages e Scripts.
Fluxo comum: crie uma ligação (connection string, test, save). Liste as tabelas remotas disponíveis; escolha quais importar. Para cada tabela importada, defina o modo de sincronização (Full / Delta) e o trigger de sincronização (cron / manual / intervalo fixo).
Espelhados, não federados: os dados importados vivem na sua própria
omnicore-db. As leituras são rápidas (Postgres local). Compromisso: desatualização
entre sincronizações.
Colunas geridas pela app: marque algumas colunas como "geridas pelo Archestack", não serão sobrescritas por sincronizações futuras. Útil quando quer anotar dados de fornecedor com as suas próprias flags de estado.
Armadilhas: a primeira sincronização de uma tabela grande pode demorar. As
sincronizações Delta exigem uma coluna que o conector possa usar como watermark, tipicamente
um timestamp modified_at.
AI Builder
Um assistente guiado onde descreve uma funcionalidade em linguagem natural e o assistente gera um plano de build, adições de schema, alterações de BE, páginas, eventos, que revê linha-a-linha e aplica. A geração do plano é feita por um LLM externo à sua escolha (Claude, ChatGPT, Gemini), o assistente compõe um prompt auto-contido para si colar e aceita a resposta JSON de volta. Já não existe um chat assistente in-app.
Fluxo comum: descreva a funcionalidade em 1-3 frases ("adicionar suporte para marcações de serviço, cada uma tem uma data, um cliente, um veículo e um estado"). Clique em Generate prompt, cole-o no seu LLM externo, cole a resposta JSON de volta no passo Import, clique em Review. Desmarque o que não quer. Clique em Apply.
Funciona bem para: funcionalidades em forma de CRUD, automações simples, extensões diretas a entidades existentes.
Menos bem para: regras de negócio não óbvias, fluxos de trabalho complexos em vários passos. O plano é um ponto de partida, reveja-o como o PR de um júnior.
Armadilhas: apply é irreversível. Para funcionalidades arriscadas, faça um backup primeiro (ou aplique num ambiente de trial, avalie, e depois reconstrua em produção a partir do Package resultante).
Object Browser
Vista em bruto de cada tabela nativa e importada, adicionar, editar, apagar linhas diretamente. Inclui uma importação CSV para carregamento em massa.
Quando recorrer:
- Carregar em massa dados de referência antes das páginas existirem (países, moedas, enums de estado).
- Depuração, ver o que está realmente numa tabela quando uma página se comporta mal.
- Edições rápidas de administração a dados ainda não expostos via uma Page.
- Importação CSV: escolha uma tabela, faça upload de um ficheiro, mapeie as colunas aos campos, pré-visualize, confirme.
Armadilhas: o Object Browser dispara Business Events (passa pelo mesmo caminho de escrita do EntityService que o front-end). A exceção é SQL direto via Database Deployments, isso contorna tudo.
Dependency Graph
Um mapa só de leitura de como os objetos de configuração no seu ambiente se referenciam uns aos outros. Oito tipos de recurso aparecem como nós, coloridos por tipo: Business Entities, Pages, Event Triggers, Script Modules, PDF Templates, Frontend Templates, Scheduled Events e Packages. Uma aresta entre dois nós significa que um recurso depende do outro. Recorra a ele para responder às perguntas "o que se partiria se eu apagar isto?" e "há algo sem uso aqui?".
O que significa uma aresta: uma Page ligada a uma Business Entity, um Event
Trigger registado numa Business Entity, um passo de ação de Page que dispara um Event Trigger,
um script que chama outro Script Module via Modules.CallAsync("Name"), um script
que renderiza um PDF Template, um Scheduled Event que dispara um Event Trigger, ou um Package
que contém um recurso. É uma vista de design-time, reflete o que a sua configuração
liga em conjunto, não o tráfego de runtime ao vivo.
Dois tipos de problema são feitos para saltar à vista:
- Loose ends (órfãos) - nós que nada referencia e que não referenciam nada. São reunidos numa banda "Loose ends" com borda vermelha no fundo do canvas. Um Script Module que ninguém chama; uma Page ligada a nada.
- Dangling references - desenhadas como arestas tracejadas vermelhas. A referência existe na configuração mas o seu alvo não pode ser encontrado, por exemplo um passo de ação de Page que ainda aponta para um Event Trigger apagado, ou um script que chama um Script Module por um nome que já não existe.
Fluxo comum: abra Dependency Graph a partir da secção Tools da sidebar. O painel esquerdo tem uma pesquisa por nome, um seletor Layout (Left to right, Top to bottom, By type, Force-directed), os interruptores Group by package, Show loose ends e Show edges, e uma checklist por tipo. Clique num nó para entrar em modo de foco: esse nó e os seus vizinhos diretos permanecem brilhantes enquanto o resto do grafo escurece, para que possa traçar exatamente o que um recurso toca. Clique no fundo do canvas para limpar o foco. Cada nó traz um pequeno botão de abrir em novo separador que salta diretamente para o editor desse recurso. A linha de estatísticas no topo reporta o número de nós, arestas, órfãos e dangling references.
Group by package: envolve os membros de cada package numa caixa tracejada etiquetada, para que possa ver um package como uma unidade e detetar os recursos que ele puxou por cascata.
Armadilhas: o grafo é construído a pedido a partir do estado atual, use o
botão de refresh depois de alterar recursos noutro lado. As arestas derivadas de scripts são
encontradas ao varrer os corpos de script à procura da forma de chamada literal
Modules.CallAsync("Name"), um module invocado através de um nome calculado não
mostrará uma aresta. Uma dangling reference vale sempre a pena corrigir; um órfão muitas vezes
não, um Script Module acabado de criar conta como órfão até que algo o chame.
Event Logs
O rasto de auditoria de tudo o que a plataforma correu, Business Events, Script Modules, Scheduled Events, sincronizações de terceiros.
Fluxo comum: abra Event Logs, defina Status como Failed, clique numa entrada. O painel de detalhe mostra o payload (estado do registo na altura, parâmetros passados), a exceção com stack trace e o timing.
Logs e Charts: a página tem dois separadores que partilham uma mesma linha de filtros. Logs é a tabela acima. Charts é um painel operacional sobre o mesmo filtro: o volume ao longo do tempo empilhado por estado, uma tendência da taxa de sucesso, uma repartição por source, os events que mais falham e os mais lentos, a duração média e máxima ao longo do tempo, uma repartição por tipo de trigger, e um mapa de calor de dia da semana por hora do dia, com os totais principais no topo. Ambos os separadores partilham um intervalo de datas De / Até (com as predefinições Últimas 1h / 24h / 7d); o separador Charts escolhe automaticamente um intervalo de tempo adequado ao período e pode atualizar-se em intervalos para monitorização em direto.
Notificações em tempo real: o ícone de sino na barra superior da aplicação admin mostra falhas não lidas via SignalR.
Armadilhas: o log pode crescer muito. As entradas antigas ficam guardadas para sempre por defeito; se o disco for uma preocupação, configure um Scheduled Event que poda entradas mais antigas que N dias.
User Management
Criar, convidar e gerir utilizadores; atribuir roles do realm. Envolve a API REST de administração do Keycloak.
Roles:
- admin - tudo; pode gerir todas as Business Units, utilizadores, roles, definições de sistema.
- owner - gere as suas próprias Business Units, pode editar páginas de administração e de runtime.
- editor - pode ver e editar páginas de runtime, mas não alterar configuração de schema/BE/eventos.
- user - só-de-leitura em páginas de runtime.
Armadilhas: despromover um utilizador de admin a meio da sessão não o expulsa, a alteração aplica-se no próximo refresh de token (tipicamente dentro de um minuto).
Business Units
Grupos suportados pelo Keycloak que filtram a visibilidade em recursos individuais. Ver Conceitos → Business Units para o modelo.
Fluxo comum: crie uma BU. Convide membros por email e escolha a role. Atribua recursos indo a cada BE / Page / Trigger ou via o painel de linked-items da BU.
Atribuições em cascata: quando atribui uma Page a uma BU, a atribuição desce em cascata para a BE a que a página se liga.
Armadilhas: a BU ativa de um utilizador é definida no seletor de BU
da barra superior e persiste em localStorage. Os utilizadores novos partem da sua
primeira BU; se uma página de listagem está suspeitosamente vazia, verifique qual BU está
ativa.
Database Backups
pg_dump noturno das três bases de dados. Disparo manual / upload / restauro a
partir da UI.
Fluxo comum: Trigger now → Download → Upload → Restore. O horário predefinido é noturno às 03:00 UTC.
Limitação de trial: os Backups estão desativados no ambiente de trial.
Branding
Alterar o nome de apresentação da aplicação, logótipo (claro + escuro) e esquema de cor primária, aplicado em runtime, sem rebuild.
Fluxo comum: defina o nome da app, faça upload de um logótipo claro e de um logótipo escuro (PNG/JPG/SVG, ≤ 10 MB), escolha uma cor de marca primária. Guarde. Recarregue o browser.
Armadilhas: o favicon não é sobreposto por Branding, está embutido no SPA.
Translations
Editor chave/valor para as strings de UI da aplicação. Adicione novas localidades, sobreponha etiquetas predefinidas por cliente.
Fluxo comum: escolha uma localidade, pesquise uma chave, escreva um valor novo, guarde. Recarregue a aplicação admin.
Armadilhas: as traduções são carregadas uma vez por sessão; utilizadores numa aba antiga não veem alterações até refrescarem. Algumas etiquetas (cabeçalhos de coluna das BEs) vêm da configuração da BE, não das traduções.
APIs invocáveis a partir de scripts
A superfície exata que os scripts podem chamar. Verificada contra o código-fonte, todos os métodos abaixo existem mesmo.
Globais
Cada script recebe estas variáveis de topo (não existem outros nomes no scope do script):
Entity- ExpandoObjectdynamic. Registo atual. Aceda a campos comEntity.column_name. MutarEntitynum trigger Before* persiste as alterações como parte da escrita em curso.OldEntity- ExpandoObjectdynamic. Registo anterior (triggers de update + delete). Só-de-leitura.Log-ILogger.Log.LogInformation("…"),Log.LogWarning(…),Log.LogError(…). Escreve nos logs do servidor e na entrada do Event Log.Db-DbHelper. Acesso à base de dados (ver abaixo).Modules-ModulesHelper. Chamar outros Script Modules:await Modules.CallAsync("ModuleName", new Dictionary<string, object?> { ["param"] = value }). DevolveTask<object?>.Pdf-ScriptPdfHelper. Renderizar um PDF template guardado pelo nome:await Pdf.GenerateAsync("invoice", new Dictionary<string, string> { ["id"] = Entity.id.ToString() })devolvebyte[];await Pdf.GenerateBase64Async(…)devolve o mesmo payload codificado em base64. Os parâmetros são reencaminhados para o data script do template como locais tipados em string.
Não existe global User, Http, Email,
Templates, ou qualquer outro.
Db - métodos de linha única + de escrita
Todos assíncronos, todos no objeto de topo Db:
await Db.GetAsync(string table, object id)- obter uma linha por chave primária. Devolvedynamic?(ounullse não encontrar).await Db.CreateAsync(string table, object values)- inserir.valuespode ser um objeto anónimo ou umDictionary<string, object?>. Dispara triggers Before/After Create. Devolveint(o novo ID).await Db.UpdateAsync(string table, object id, object values)- atualizar por PK. Dispara triggers Before/After Update.await Db.DeleteAsync(string table, object id)- apagar por PK. Dispara trigger Before Delete.
Db - construtor fluente de queries
Comece com Db.From(table). Encadeie filtros, depois um terminal:
.Where(string column, string op, object? value = null)- adicionar uma cláusula WHERE. Operadores:=,!=/<>,>,>=,<,<=,LIKE,ILIKE,IN,IS NULL,IS NOT NULL. Encadeie várias chamadas.Where(...)para AND..OrderBy(string column, bool desc = false)- definir ORDER BY. Apenas um permitido por query..Limit(int limit)- máximo de linhas. Predefinição é 1000.
Terminais (cada um corre a query):
await ...ToListAsync()- devolveList<dynamic>.await ...FirstAsync()- devolvedynamic?(primeira correspondência ou null). Temporariamente define o limite para 1.await ...CountAsync()- devolveint.
Não existe SumAsync, MaxAsync,
FirstOrDefaultAsync ou SingleAsync. Para agregações, vá buscar com
ToListAsync() e reduza em C#.
Exemplo trabalhado
// Get a row by ID, query a list, calculate a sum, update.
var order = await Db.GetAsync("orders", 42);
if (order == null) return false;
var items = await Db.From("order_items")
.Where("order_id", "=", order.id)
.OrderBy("id")
.ToListAsync();
decimal totalAmount = 0;
foreach (var item in items) {
totalAmount += (decimal)(item.amount ?? 0);
}
await Db.UpdateAsync("orders", 42, new {
total = totalAmount,
updated_at = DateTime.UtcNow
});
return true; Modo de simulação
Durante a simulação de trigger (o botão Run Simulation num Business Event), a
plataforma define Db.SimulationMode = true. Todas as operações de escrita
(CreateAsync, UpdateAsync, DeleteAsync) correm dentro
de uma transação PostgreSQL que é sempre revertida no fim. As operações de leitura funcionam
normalmente. É isto que torna Run Simulation seguro para usar contra dados reais.
Modules
await Modules.CallAsync(string moduleName, Dictionary<string, object?>? parameters = null)- chamar outro Script Module pelo nome. Os parâmetros tornam-se variáveis tipadas no script do módulo chamado. DevolveTask<object?>(o que quer que o módulo tenha devolvido).
Expressões de template (ações de Business Event)
A configuração de ações usa chavetas {{ … }}. A lista completa de tokens válidos:
{{ Entity.column_name }}/{{ Entity.id }}{{ OldEntity.column_name }}{{ now() }}/{{ getdate() }}- datetime UTC ISO 8601{{ today() }}- string de data{{ guid() }}/{{ newid() }}- GUID novo{{ year() }},{{ month() }},{{ day() }},{{ timestamp() }}- segundos Unix{{ empty() }},{{ null() }}- Agregações dentro de um contexto de join:
{{ SUM(column) }},{{ AVG() }},{{ COUNT() }},{{ MIN() }},{{ MAX() }} - Aritmética:
{{ Entity.quantity * Entity.price }}- avaliada após substituição viaDataTable.Compute()
Não existe {{ user.email }} nem outro token com âmbito de utilizador.