--!strict
-- state.luau — estado mutável compartilhado entre todos os handlers/*.luau
-- (mesmo interpretador, mesma tabela: `require("../state")` é cacheado por
-- identidade — pelo CAMINHO resolvido do arquivo, não pela string pedida —
-- então toda mutação feita por um handler é vista pelos demais).
--
-- Convenção de `require` neste projeto (glacier-ui 0.22.0+: resolução
-- relativa ao ARQUIVO que chama, como Node.js/Lua padrão — ver
-- CHANGELOG do glacier-ui e docs/luau-modularizacao-pacotes.md):
-- - Irmão no MESMO diretório/pacote → nome nu: `require("stream")` de
-- dentro de `handlers/` acha `handlers/stream.luau`.
-- - Pacote PAI (este arquivo, `helpers.luau`, `format.luau`, `net/api.luau`,
-- todos na raiz de `views/scripts/`) a partir de dentro de `handlers/`
-- ou `format/` → prefixo explícito `../`: `require("../state")`.
-- - Do script de ENTRADA (`app.luau`, que fica na raiz) → caminho completo
-- nu: `require("handlers/connection")`, `require("format/time")`.
-- Ver `docs/luau-modularizacao-pacotes.md` (raiz do repo rustploy) para a
-- investigação completa que motivou essa convenção.
local Api = require("net/api")
-- `name` é capturado ao armar o deploy (start_deploy) só para a notificação do
-- SO no desfecho: o evento DeployStateChanged identifica o serviço por
-- `service_id`, não pelo nome. (O evento NÃO é magro como este comentário já
-- afirmou: além de `deployment_id`/`service_id`/`state`/`timestamp`, ele traz
-- `message` — o motivo da falha — que o handler de stream usa na notificação e
-- no toast. Ver docs/plano-erro-de-deploy-invisivel.md.)
export type DeployTrack = {
service_id: string,
deployment_id: string,
running: boolean,
name: string,
}
export type State = {
api: Api.Client?, -- cliente Api conectado
state_conn: any, -- handle do stream SSE
snap: any, -- último snapshot decodificado (para refiltrar)
last_pairs: { any }, -- serviços normalizados { svc, proj } do snapshot
-- service_id → ContainerMetricsPoint (bus)
metrics_by_id: { [string]: any },
search_term: string, -- termo de busca corrente (minúsculas)
-- Logs (runtime/build) NÃO vivem mais aqui: cada tipo roda numa janela
-- isolada (log_window.luau) com seu próprio ring e SSE dedicada, para não
-- pesar na reavaliação da árvore da janela principal. Ver
-- handlers/services (open_logs_window / deployment_logs) e o daemon
-- (endpoints /api/.../logs).
deploy_track: DeployTrack,
-- catálogo completo de templates (filtrar busca)
new_service_templates_all: { any },
-- service_id → webhook revelado no painel "Em execução"
running_revealed: { [string]: boolean },
-- service_id → ServiceWarmStatus (snapshot)
service_warm_by_id: { [string]: any },
-- job_id → Job cru (do snapshot) — job_toggle precisa do
-- compose/name/main_service completos pra reenviar o JobUpdate.
jobs_by_id: { [string]: any },
-- job_id → true entre o click em "Rodar agora" e o refresh_now() que
-- confirma o novo job_run — trava double-click durante o round-trip da RPC
-- (o botão só reflete `running` do snapshot DEPOIS disso).
jobs_inflight: { [string]: boolean },
-- DockerCleanupConfig.last_run_at cru (ISO8601 ou nil), round-trip opaco:
-- preserva o horário real entre saves do formulário de Manutenção, pra um
-- agendamento IntervalHours não reiniciar a contagem a cada "Save" — ver
-- handlers/settings.luau.
docker_cleanup_last_run_at_raw: any,
-- `checked_at` do último UpdateInfo mostrado na aba Atualizações: o
-- snapshot só reescreve a aba quando há consulta nova (ver
-- handlers/stream.luau::apply_update_info).
update_checked_at: string,
-- Aviso deixado por "Atualizar daemon"/"Reverter" para a tela de login: o
-- daemon reinicia, o stream cai e a janela volta ao login antes de dar tempo
-- de ler a mensagem da aba (ver handlers/stream.luau::on_close). Vazio = nada.
restart_notice: string,
}
local shared_state: State = {
api = nil,
state_conn = nil,
snap = nil,
last_pairs = {},
metrics_by_id = {},
search_term = "",
deploy_track = {
service_id = "",
deployment_id = "",
running = false,
name = "",
},
new_service_templates_all = {},
running_revealed = {},
service_warm_by_id = {},
jobs_by_id = {},
jobs_inflight = {},
docker_cleanup_last_run_at_raw = nil,
update_checked_at = "",
restart_notice = "",
}
return shared_state