--!strict
-- Definições dos globais que o motor glacier-ui injeta no interpretador Luau em
-- runtime (não existem como arquivo). Consumido só pelo type-checker (luau-lsp):
-- o mlua ignora tipos/anotações em runtime. Carregue com
-- luau-lsp analyze --definitions=views/scripts/glacier.d.luau ...
export type FetchResult = {
ok: boolean,
status: number,
body: string,
error: string,
}
export type StreamHandle = {
id: number,
close: (self: StreamHandle) -> any,
send: (self: StreamHandle, text: string) -> any,
}
-- Contexto global do motor: chave→valor string (o motor coage tudo p/ string).
declare ctx: { [string]: string }
-- Valor do on_change/on_toggle/ação-com-sufixo (nil quando a ação não traz valor).
declare value: string?
-- Tamanho atual da janela em px lógicos (o que também alimenta @media no GSS).
export type Viewport = {
width: number,
height: number,
}
declare function viewport(): Viewport
-- HTTP, ou leitura de arquivo local quando a URL começa com `file://`
-- (glacier-ui 0.49+): devolve o mesmo FetchResult, com o conteúdo no `body`.
declare function fetch(url: string, opts: any?): FetchResult
-- Escrita de arquivo local (glacier-ui 0.49+), contraparte do `fetch("file://…")`.
-- Devolve `true` no sucesso, ou `false, mensagem` na falha.
declare function write_file(path: string, contents: string): (boolean, string?)
-- Idem, acrescentando ao fim (glacier-ui 0.49+).
declare function append_file(path: string, contents: string): (boolean, string?)
-- Compacta a árvore de `source` (diretório) num `.zip` em `dest` (glacier-ui
-- 0.83+). Síncrono (I/O local). `(true)` no sucesso, `(false, mensagem)` na falha.
declare function zip_dir(source: string, dest: string): (boolean, string?)
-- `.zip` de entradas de TEXTO, sem diretório de staging (glacier-ui 0.123+).
-- `zip_read` entrega todas as entradas; `text` falta em diretório e em conteúdo
-- que não é UTF-8. Quem decide quais nomes aceitar é o chamador.
export type ZipEntry = { name: string, dir: boolean?, text: string? }
declare function zip_write(dest: string, entries: { ZipEntry }): (boolean, string?)
declare function zip_read(source: string): { ok: boolean, entries: { ZipEntry }?, error: string? }
-- Diálogos nativos do SO (glacier-ui 0.49+). SUSPENDEM a corrotina até o usuário
-- escolher/cancelar; devolvem o caminho escolhido, ou `nil` se cancelou.
-- `opts`: { title?, starting_dir?, default_name?, filters? }.
declare function open_file(opts: any?): string?
declare function save_file(opts: any?): string?
declare function pick_folder(opts: any?): string?
-- Streams de vida longa. NÃO suspendem: registram o stream e devolvem o handle
-- na hora. Cada callback é uma FUNÇÃO (closure e upvalue funcionam) — o motor
-- também aceita o nome de uma função global, como atalho, mas o tipo abaixo
-- guia para a forma boa: o nome obriga o handler a ser global, não fecha sobre
-- nada, e falha em silêncio quando está errado.
export type StreamOptions = {
headers: { [string]: string }?,
-- "window" (padrão): vive até a janela fechar. "screen": o motor fecha ao SAIR
-- da tela dona (depois do `on_leave`), com `on_close`. Abra em `on_enter`.
scope: ("screen" | "window")?,
on_open: (() -> ())?,
on_message: ((data: string) -> ())?,
on_error: ((message: string) -> ())?,
on_close: (() -> ())?,
}
declare function sse(url: string, opts: StreamOptions?): StreamHandle
declare function websocket(url: string, opts: StreamOptions?): StreamHandle
declare function toast(opts: any): ()
-- Notificação nativa do SO (glacier-ui 0.42+): `notify({ title?, body? })` ou
-- `notify("mensagem")`. Diferente de `toast` (efêmero, dentro da janela).
declare function notify(opts: any): ()
-- Copia `text` p/ a área de transferência (glacier-ui 0.126+); não informa sucesso — chame `toast` em seguida.
declare function copy(text: any): ()
declare function confirm(opts: any): boolean
-- Multi-janela (glacier-ui 0.36+/0.37+): abrir janela, mensagear entre janelas e
-- fechar a própria. `on_broadcast(event, payload)` é definido pelo usuário (a
-- janela receptora), não injetado — por isso não é declarado aqui.
declare function open_window(opts: any): ()
declare function broadcast(event: string, payload: any?): ()
declare function close_window(): ()
-- Anexa texto ao fim do <textarea> ligado a `binding` (chave do `value`), de
-- forma incremental (o motor insere no Content sem recriá-lo — preserva scroll).
declare function append_textarea(binding: string, text: string): ()
declare json: {
decode: (s: string) -> any,
encode: (v: any) -> string,
array: <T>(t: { T }) -> { T },
}
-- Persistência local em JSON, análoga ao `localStorage` do browser: sobrevive a
-- um restart do processo (ao contrário do `ctx`, que é só memória). `set` grava
-- qualquer valor JSON-serializável (string, número, booleano, tabela); `get`
-- devolve o valor guardado ou nil; `remove` apaga a chave. No rustploy grava em
-- `~/.local/share/rustploy/.glacier-storage/app.json` (raiz definida no Rust via
-- `GlacierDaemon::storage_dir`, glacier-ui 0.45+).
declare storage: {
get: (key: string) -> any,
set: (key: string, value: any) -> (),
remove: (key: string) -> (),
}
-- Data e hora sobre strings ISO (glacier-ui 0.72+; fuso e epoch na 0.73). Um
-- valor SEM fuso é hora local — é o que `today`/`now` devolvem e o que o
-- `<timeedit>` guarda; um valor COM fuso (`2026-07-06T12:34:56Z`, `...-03:00`,
-- fração de segundo opcional) usa o dele. É esse segundo formato que o daemon
-- manda em todo `started_at`/`created_at`, e `to_local` é o que o traz para a
-- hora de parede da tela. Ver `fmt/time.luau`.
export type DateDelta = {
years: number?,
months: number?,
days: number?,
hours: number?,
minutes: number?,
seconds: number?,
}
declare date: {
today: () -> string,
now: (segundos: boolean?) -> string,
time: (segundos: boolean?) -> string,
parse: (iso: string) -> { [string]: number }?,
valid: (iso: string) -> boolean,
weekday: (iso: string) -> number?,
date_of: (iso: string) -> string?,
time_of: (iso: string) -> string?,
days_in_month: (ano: number, mes: number) -> number,
compare: (a: string, b: string) -> number?,
is_before: (a: string, b: string) -> boolean,
is_after: (a: string, b: string) -> boolean,
add: (iso: string, delta: DateDelta?) -> string?,
diff: (a: string, b: string) -> number?,
diff_seconds: (a: string, b: string) -> number?,
format: (iso: string, fmt: string) -> string?,
epoch: (iso: string) -> number?,
from_epoch: (segundos: number, utc: boolean?) -> string?,
to_local: (iso: string) -> string?,
to_utc: (iso: string) -> string?,
}