expxdev 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +137 -0
- package/dist/cli/argumentos.d.ts +22 -0
- package/dist/cli/argumentos.js +85 -0
- package/dist/cli/argumentos.js.map +1 -0
- package/dist/cli/expx-bin.d.ts +2 -0
- package/dist/cli/expx-bin.js +40 -0
- package/dist/cli/expx-bin.js.map +1 -0
- package/dist/cli/expx.d.ts +13 -0
- package/dist/cli/expx.js +123 -0
- package/dist/cli/expx.js.map +1 -0
- package/dist/cli/init-flags.d.ts +34 -0
- package/dist/cli/init-flags.js +83 -0
- package/dist/cli/init-flags.js.map +1 -0
- package/dist/cli/init.d.ts +34 -0
- package/dist/cli/init.js +103 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/principal.d.ts +2 -0
- package/dist/cli/principal.js +107 -0
- package/dist/cli/principal.js.map +1 -0
- package/dist/cli/projeto.d.ts +19 -0
- package/dist/cli/projeto.js +28 -0
- package/dist/cli/projeto.js.map +1 -0
- package/dist/cli/selecao.d.ts +19 -0
- package/dist/cli/selecao.js +28 -0
- package/dist/cli/selecao.js.map +1 -0
- package/dist/cli/selecionar.d.ts +23 -0
- package/dist/cli/selecionar.js +45 -0
- package/dist/cli/selecionar.js.map +1 -0
- package/dist/cli/subcomandos.d.ts +25 -0
- package/dist/cli/subcomandos.js +43 -0
- package/dist/cli/subcomandos.js.map +1 -0
- package/dist/doctor/efeito.d.ts +17 -0
- package/dist/doctor/efeito.js +18 -0
- package/dist/doctor/efeito.js.map +1 -0
- package/dist/doctor/verificadores.d.ts +21 -0
- package/dist/doctor/verificadores.js +158 -0
- package/dist/doctor/verificadores.js.map +1 -0
- package/dist/harness/backup.d.ts +15 -0
- package/dist/harness/backup.js +29 -0
- package/dist/harness/backup.js.map +1 -0
- package/dist/harness/instalar.d.ts +31 -0
- package/dist/harness/instalar.js +43 -0
- package/dist/harness/instalar.js.map +1 -0
- package/dist/harness/opencode.d.ts +18 -0
- package/dist/harness/opencode.js +32 -0
- package/dist/harness/opencode.js.map +1 -0
- package/dist/harness/settings.d.ts +36 -0
- package/dist/harness/settings.js +66 -0
- package/dist/harness/settings.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/nucleo/busca.d.ts +28 -0
- package/dist/nucleo/busca.js +29 -0
- package/dist/nucleo/busca.js.map +1 -0
- package/dist/nucleo/caminhos.d.ts +21 -0
- package/dist/nucleo/caminhos.js +64 -0
- package/dist/nucleo/caminhos.js.map +1 -0
- package/dist/nucleo/catalogo.d.ts +20 -0
- package/dist/nucleo/catalogo.js +50 -0
- package/dist/nucleo/catalogo.js.map +1 -0
- package/dist/nucleo/integridade.d.ts +20 -0
- package/dist/nucleo/integridade.js +75 -0
- package/dist/nucleo/integridade.js.map +1 -0
- package/dist/nucleo/layout.d.ts +23 -0
- package/dist/nucleo/layout.js +73 -0
- package/dist/nucleo/layout.js.map +1 -0
- package/dist/nucleo/lock.d.ts +61 -0
- package/dist/nucleo/lock.js +96 -0
- package/dist/nucleo/lock.js.map +1 -0
- package/dist/nucleo/versao.d.ts +35 -0
- package/dist/nucleo/versao.js +63 -0
- package/dist/nucleo/versao.js.map +1 -0
- package/dist/parser/conformidade/regras.d.ts +41 -0
- package/dist/parser/conformidade/regras.js +209 -0
- package/dist/parser/conformidade/regras.js.map +1 -0
- package/dist/parser/descoberta/trabalhos.d.ts +35 -0
- package/dist/parser/descoberta/trabalhos.js +28 -0
- package/dist/parser/descoberta/trabalhos.js.map +1 -0
- package/dist/parser/descoberta/varredura.d.ts +4 -0
- package/dist/parser/descoberta/varredura.js +79 -0
- package/dist/parser/descoberta/varredura.js.map +1 -0
- package/dist/parser/esquema/cabecalho.d.ts +60 -0
- package/dist/parser/esquema/cabecalho.js +57 -0
- package/dist/parser/esquema/cabecalho.js.map +1 -0
- package/dist/parser/esquema/enums.d.ts +114 -0
- package/dist/parser/esquema/enums.js +64 -0
- package/dist/parser/esquema/enums.js.map +1 -0
- package/dist/parser/esquema/kinds.d.ts +768 -0
- package/dist/parser/esquema/kinds.js +231 -0
- package/dist/parser/esquema/kinds.js.map +1 -0
- package/dist/parser/leitura/arquivo.d.ts +9 -0
- package/dist/parser/leitura/arquivo.js +25 -0
- package/dist/parser/leitura/arquivo.js.map +1 -0
- package/dist/parser/leitura/frontmatter.d.ts +31 -0
- package/dist/parser/leitura/frontmatter.js +77 -0
- package/dist/parser/leitura/frontmatter.js.map +1 -0
- package/dist/parser/leitura/rejeicao.d.ts +43 -0
- package/dist/parser/leitura/rejeicao.js +73 -0
- package/dist/parser/leitura/rejeicao.js.map +1 -0
- package/dist/parser/projeto/montar.d.ts +62 -0
- package/dist/parser/projeto/montar.js +149 -0
- package/dist/parser/projeto/montar.js.map +1 -0
- package/dist/plugin/atomico.d.ts +13 -0
- package/dist/plugin/atomico.js +42 -0
- package/dist/plugin/atomico.js.map +1 -0
- package/dist/plugin/manifestos.d.ts +38 -0
- package/dist/plugin/manifestos.js +57 -0
- package/dist/plugin/manifestos.js.map +1 -0
- package/dist/plugin/montagem.d.ts +22 -0
- package/dist/plugin/montagem.js +30 -0
- package/dist/plugin/montagem.js.map +1 -0
- package/dist/relatorio/markdown.d.ts +22 -0
- package/dist/relatorio/markdown.js +0 -0
- package/dist/relatorio/markdown.js.map +1 -0
- package/dist/relatorio/pagina.d.ts +22 -0
- package/dist/relatorio/pagina.js +338 -0
- package/dist/relatorio/pagina.js.map +1 -0
- package/dist/servidor/estado.d.ts +16 -0
- package/dist/servidor/estado.js +16 -0
- package/dist/servidor/estado.js.map +1 -0
- package/dist/servidor/http.d.ts +22 -0
- package/dist/servidor/http.js +164 -0
- package/dist/servidor/http.js.map +1 -0
- package/dist/servidor/observador.d.ts +12 -0
- package/dist/servidor/observador.js +37 -0
- package/dist/servidor/observador.js.map +1 -0
- package/dist/servidor/painel.d.ts +24 -0
- package/dist/servidor/painel.js +49 -0
- package/dist/servidor/painel.js.map +1 -0
- package/dist/teste/layouts-fixture.d.ts +16 -0
- package/dist/teste/layouts-fixture.js +9 -0
- package/dist/teste/layouts-fixture.js.map +1 -0
- package/dist/teste/projeto-temporario.d.ts +14 -0
- package/dist/teste/projeto-temporario.js +16 -0
- package/dist/teste/projeto-temporario.js.map +1 -0
- package/dist/teste/repo-fixture.d.ts +27 -0
- package/dist/teste/repo-fixture.js +49 -0
- package/dist/teste/repo-fixture.js.map +1 -0
- package/dist/update/comparar.d.ts +33 -0
- package/dist/update/comparar.js +67 -0
- package/dist/update/comparar.js.map +1 -0
- package/dist/update/compatibilidade.d.ts +19 -0
- package/dist/update/compatibilidade.js +36 -0
- package/dist/update/compatibilidade.js.map +1 -0
- package/dist/update/flags.d.ts +47 -0
- package/dist/update/flags.js +123 -0
- package/dist/update/flags.js.map +1 -0
- package/dist/update/modificacao.d.ts +23 -0
- package/dist/update/modificacao.js +36 -0
- package/dist/update/modificacao.js.map +1 -0
- package/package.json +73 -0
- package/ui/dist/assets/index-BmDTogQZ.js +14 -0
- package/ui/dist/assets/index-DUzbt2M7.css +1 -0
- package/ui/dist/index.html +13 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { renderizar, escapar } from "./markdown.js";
|
|
2
|
+
const ROTULO_TIPO = {
|
|
3
|
+
tecnico: "Relatório técnico",
|
|
4
|
+
uso: "Relatório de uso",
|
|
5
|
+
};
|
|
6
|
+
const SUBTITULO = {
|
|
7
|
+
tecnico: "Documento de engenharia — causa, correção e cobertura de teste.",
|
|
8
|
+
uso: "Documento para o cliente — o que mudou, em linguagem de negócio.",
|
|
9
|
+
};
|
|
10
|
+
function sumarioHtml(itens) {
|
|
11
|
+
if (itens.length < 3)
|
|
12
|
+
return "";
|
|
13
|
+
return `
|
|
14
|
+
<nav class="sumario" aria-label="Sumário">
|
|
15
|
+
<h2>Sumário</h2>
|
|
16
|
+
<ol>
|
|
17
|
+
${itens
|
|
18
|
+
.map((i) => `<li class="n${String(i.nivel)}"><a href="#${i.id}">${escapar(i.texto)}</a></li>`)
|
|
19
|
+
.join("\n ")}
|
|
20
|
+
</ol>
|
|
21
|
+
</nav>`;
|
|
22
|
+
}
|
|
23
|
+
function metaHtml(d) {
|
|
24
|
+
const linhas = [
|
|
25
|
+
["Ocorrência", d.oc_id],
|
|
26
|
+
["Tipo", d.tipo_ocorrencia],
|
|
27
|
+
["Fechado em", d.fechado_em],
|
|
28
|
+
["Módulos", d.modulo_afetado.length > 0 ? d.modulo_afetado.join(", ") : "—"],
|
|
29
|
+
];
|
|
30
|
+
if (d.tipo === "tecnico") {
|
|
31
|
+
if (d.arquivos_alterados !== undefined) {
|
|
32
|
+
linhas.push(["Arquivos alterados", String(d.arquivos_alterados.length)]);
|
|
33
|
+
}
|
|
34
|
+
if (d.testes_adicionados !== undefined && d.testes_adicionados !== null) {
|
|
35
|
+
linhas.push(["Testes adicionados", String(d.testes_adicionados)]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return `
|
|
39
|
+
<dl class="meta">
|
|
40
|
+
${linhas.map(([k, v]) => `<div><dt>${escapar(k)}</dt><dd>${escapar(v)}</dd></div>`).join("\n ")}
|
|
41
|
+
</dl>`;
|
|
42
|
+
}
|
|
43
|
+
function arquivosHtml(d) {
|
|
44
|
+
if (d.tipo !== "tecnico" || !d.arquivos_alterados || d.arquivos_alterados.length === 0)
|
|
45
|
+
return "";
|
|
46
|
+
return `
|
|
47
|
+
<section class="anexo">
|
|
48
|
+
<h2>Arquivos alterados</h2>
|
|
49
|
+
<ul class="arquivos">
|
|
50
|
+
${d.arquivos_alterados.map((a) => `<li><code>${escapar(a)}</code></li>`).join("\n ")}
|
|
51
|
+
</ul>
|
|
52
|
+
</section>`;
|
|
53
|
+
}
|
|
54
|
+
export function paginaRelatorio(d) {
|
|
55
|
+
const { html, sumario } = renderizar(d.corpo);
|
|
56
|
+
const rotulo = ROTULO_TIPO[d.tipo];
|
|
57
|
+
const titulo = `${rotulo} — ${d.titulo}`;
|
|
58
|
+
// O .md vai embutido em base64 para o botão de download funcionar offline,
|
|
59
|
+
// depois que o painel já tiver sido encerrado.
|
|
60
|
+
const md = Buffer.from(d.corpo, "utf8").toString("base64");
|
|
61
|
+
/**
|
|
62
|
+
* String literal segura dentro de <script>.
|
|
63
|
+
*
|
|
64
|
+
* JSON.stringify NÃO basta: ele não escapa `<`, então um valor contendo
|
|
65
|
+
* `</script>` fecharia a tag e o resto viraria HTML — XSS a partir do
|
|
66
|
+
* frontmatter de um arquivo. Escapamos a barra e os sinais de menor/maior.
|
|
67
|
+
*/
|
|
68
|
+
const literal = (s) => JSON.stringify(s).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028|\u2029/g, "");
|
|
69
|
+
return `<!doctype html>
|
|
70
|
+
<html lang="pt-BR">
|
|
71
|
+
<head>
|
|
72
|
+
<meta charset="utf-8" />
|
|
73
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
74
|
+
<title>${escapar(titulo)}</title>
|
|
75
|
+
<style>
|
|
76
|
+
:root {
|
|
77
|
+
--tinta: #16181d;
|
|
78
|
+
--tinta-suave: #5a6169;
|
|
79
|
+
--tinta-tenue: #878d96;
|
|
80
|
+
--papel: #ffffff;
|
|
81
|
+
--fundo: #f4f5f7;
|
|
82
|
+
--linha: #e2e5e9;
|
|
83
|
+
--linha-forte: #cbd1d8;
|
|
84
|
+
--marca: ${d.tipo === "tecnico" ? "#2f5d8a" : "#2f6f4e"};
|
|
85
|
+
--marca-fraca: ${d.tipo === "tecnico" ? "#eaf1f8" : "#e9f2ec"};
|
|
86
|
+
--serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
|
|
87
|
+
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
|
|
88
|
+
--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
* { box-sizing: border-box; }
|
|
92
|
+
|
|
93
|
+
body {
|
|
94
|
+
margin: 0;
|
|
95
|
+
background: var(--fundo);
|
|
96
|
+
color: var(--tinta);
|
|
97
|
+
font-family: var(--sans);
|
|
98
|
+
font-size: 16px;
|
|
99
|
+
line-height: 1.65;
|
|
100
|
+
-webkit-font-smoothing: antialiased;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* ---- barra de ações ---- */
|
|
104
|
+
.acoes {
|
|
105
|
+
position: sticky; top: 0; z-index: 10;
|
|
106
|
+
display: flex; align-items: center; gap: 8px;
|
|
107
|
+
padding: 10px 20px;
|
|
108
|
+
background: rgba(255,255,255,.85);
|
|
109
|
+
backdrop-filter: saturate(180%) blur(12px);
|
|
110
|
+
border-bottom: 1px solid var(--linha);
|
|
111
|
+
}
|
|
112
|
+
.acoes .id {
|
|
113
|
+
font-family: var(--mono); font-size: 12px; color: var(--tinta-tenue);
|
|
114
|
+
margin-right: auto;
|
|
115
|
+
}
|
|
116
|
+
.acoes button {
|
|
117
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
118
|
+
font: inherit; font-size: 13px; font-weight: 500;
|
|
119
|
+
padding: 7px 14px; border-radius: 6px; cursor: pointer;
|
|
120
|
+
border: 1px solid var(--linha-forte); background: #fff; color: var(--tinta);
|
|
121
|
+
}
|
|
122
|
+
.acoes button:hover { border-color: var(--marca); color: var(--marca); }
|
|
123
|
+
.acoes button.principal {
|
|
124
|
+
background: var(--marca); border-color: var(--marca); color: #fff;
|
|
125
|
+
}
|
|
126
|
+
.acoes button.principal:hover { filter: brightness(1.08); color: #fff; }
|
|
127
|
+
.acoes svg { width: 15px; height: 15px; }
|
|
128
|
+
|
|
129
|
+
/* ---- folha ---- */
|
|
130
|
+
.folha {
|
|
131
|
+
max-width: 820px; margin: 26px auto 60px;
|
|
132
|
+
background: var(--papel); border: 1px solid var(--linha);
|
|
133
|
+
border-radius: 4px; box-shadow: 0 1px 3px rgba(22,24,29,.06), 0 12px 32px rgba(22,24,29,.05);
|
|
134
|
+
padding: 60px 68px 72px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* ---- capa ---- */
|
|
138
|
+
.capa { border-bottom: 2px solid var(--tinta); padding-bottom: 26px; margin-bottom: 30px; }
|
|
139
|
+
.selo {
|
|
140
|
+
display: inline-block; font-size: 11px; font-weight: 700;
|
|
141
|
+
letter-spacing: .12em; text-transform: uppercase;
|
|
142
|
+
color: var(--marca); background: var(--marca-fraca);
|
|
143
|
+
padding: 4px 10px; border-radius: 3px; margin-bottom: 16px;
|
|
144
|
+
}
|
|
145
|
+
.capa h1 {
|
|
146
|
+
font-family: var(--serif); font-weight: 600;
|
|
147
|
+
font-size: 34px; line-height: 1.18; letter-spacing: -.015em;
|
|
148
|
+
margin: 0 0 10px;
|
|
149
|
+
}
|
|
150
|
+
.capa .subtitulo { font-size: 15px; color: var(--tinta-suave); margin: 0; }
|
|
151
|
+
|
|
152
|
+
/* ---- metadados ---- */
|
|
153
|
+
dl.meta {
|
|
154
|
+
display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
155
|
+
gap: 18px 26px; margin: 0 0 34px; padding: 20px 24px;
|
|
156
|
+
background: var(--fundo); border-radius: 6px;
|
|
157
|
+
}
|
|
158
|
+
dl.meta div { min-width: 0; }
|
|
159
|
+
dl.meta dt {
|
|
160
|
+
font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
|
|
161
|
+
text-transform: uppercase; color: var(--tinta-tenue); margin-bottom: 4px;
|
|
162
|
+
}
|
|
163
|
+
dl.meta dd { margin: 0; font-size: 14.5px; font-weight: 500; word-break: break-word; }
|
|
164
|
+
|
|
165
|
+
/* ---- sumário ---- */
|
|
166
|
+
.sumario {
|
|
167
|
+
margin: 0 0 34px; padding: 20px 24px;
|
|
168
|
+
border: 1px solid var(--linha); border-radius: 6px;
|
|
169
|
+
}
|
|
170
|
+
.sumario h2 {
|
|
171
|
+
font-size: 11px; font-weight: 700; letter-spacing: .09em;
|
|
172
|
+
text-transform: uppercase; color: var(--tinta-tenue);
|
|
173
|
+
margin: 0 0 12px; padding: 0; border: none;
|
|
174
|
+
}
|
|
175
|
+
.sumario ol { list-style: none; margin: 0; padding: 0; counter-reset: s; }
|
|
176
|
+
.sumario li { margin: 5px 0; font-size: 14px; }
|
|
177
|
+
.sumario li.n2 { padding-left: 18px; font-size: 13.5px; }
|
|
178
|
+
.sumario li.n3 { padding-left: 36px; font-size: 13px; color: var(--tinta-suave); }
|
|
179
|
+
.sumario a { color: var(--tinta); text-decoration: none; }
|
|
180
|
+
.sumario a:hover { color: var(--marca); text-decoration: underline; }
|
|
181
|
+
|
|
182
|
+
/* ---- corpo ---- */
|
|
183
|
+
.corpo { font-size: 16px; }
|
|
184
|
+
.corpo h1, .corpo h2, .corpo h3, .corpo h4 {
|
|
185
|
+
font-family: var(--serif); font-weight: 600; letter-spacing: -.01em;
|
|
186
|
+
scroll-margin-top: 70px;
|
|
187
|
+
}
|
|
188
|
+
.corpo h1 { font-size: 27px; margin: 40px 0 14px; }
|
|
189
|
+
.corpo h2 {
|
|
190
|
+
font-size: 21px; margin: 36px 0 13px;
|
|
191
|
+
padding-bottom: 7px; border-bottom: 1px solid var(--linha);
|
|
192
|
+
}
|
|
193
|
+
.corpo h3 { font-size: 17.5px; margin: 28px 0 10px; }
|
|
194
|
+
.corpo h4 { font-size: 15.5px; margin: 22px 0 8px; }
|
|
195
|
+
.corpo p { margin: 0 0 15px; }
|
|
196
|
+
.corpo ul, .corpo ol { margin: 0 0 15px; padding-left: 24px; }
|
|
197
|
+
.corpo li { margin: 5px 0; }
|
|
198
|
+
.corpo a { color: var(--marca); }
|
|
199
|
+
.corpo strong { font-weight: 650; }
|
|
200
|
+
|
|
201
|
+
.corpo code {
|
|
202
|
+
font-family: var(--mono); font-size: .875em;
|
|
203
|
+
background: var(--fundo); border: 1px solid var(--linha);
|
|
204
|
+
padding: 1px 5px; border-radius: 4px;
|
|
205
|
+
}
|
|
206
|
+
.corpo pre.bloco {
|
|
207
|
+
background: #1f2228; color: #e6e9ee;
|
|
208
|
+
padding: 16px 18px; border-radius: 6px; overflow-x: auto;
|
|
209
|
+
font-family: var(--mono); font-size: 13px; line-height: 1.6;
|
|
210
|
+
margin: 0 0 18px;
|
|
211
|
+
}
|
|
212
|
+
.corpo pre.bloco code { background: none; border: none; padding: 0; color: inherit; font-size: inherit; }
|
|
213
|
+
|
|
214
|
+
.corpo blockquote {
|
|
215
|
+
margin: 0 0 18px; padding: 12px 18px;
|
|
216
|
+
border-left: 3px solid var(--marca); background: var(--marca-fraca);
|
|
217
|
+
border-radius: 0 4px 4px 0; color: var(--tinta-suave);
|
|
218
|
+
}
|
|
219
|
+
.corpo blockquote p:last-child { margin-bottom: 0; }
|
|
220
|
+
.corpo hr { border: none; border-top: 1px solid var(--linha); margin: 30px 0; }
|
|
221
|
+
|
|
222
|
+
.rolagem { overflow-x: auto; margin: 0 0 18px; }
|
|
223
|
+
.corpo table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
|
|
224
|
+
.corpo th {
|
|
225
|
+
text-align: left; font-size: 11px; font-weight: 700;
|
|
226
|
+
letter-spacing: .06em; text-transform: uppercase; color: var(--tinta-tenue);
|
|
227
|
+
padding: 9px 12px; border-bottom: 2px solid var(--linha-forte);
|
|
228
|
+
}
|
|
229
|
+
.corpo td { padding: 9px 12px; border-bottom: 1px solid var(--linha); vertical-align: top; }
|
|
230
|
+
.corpo tbody tr:last-child td { border-bottom: none; }
|
|
231
|
+
|
|
232
|
+
/* ---- anexo ---- */
|
|
233
|
+
.anexo { margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--linha); }
|
|
234
|
+
.anexo h2 {
|
|
235
|
+
font-family: var(--serif); font-size: 19px; font-weight: 600; margin: 0 0 12px;
|
|
236
|
+
}
|
|
237
|
+
ul.arquivos { list-style: none; margin: 0; padding: 0; }
|
|
238
|
+
ul.arquivos li { margin: 5px 0; }
|
|
239
|
+
ul.arquivos code { font-size: 13px; }
|
|
240
|
+
|
|
241
|
+
/* ---- rodapé ---- */
|
|
242
|
+
.rodape {
|
|
243
|
+
margin-top: 44px; padding-top: 18px; border-top: 1px solid var(--linha);
|
|
244
|
+
font-size: 12px; color: var(--tinta-tenue);
|
|
245
|
+
display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* ---- impressão / PDF ---- */
|
|
249
|
+
@page { size: A4; margin: 18mm 16mm; }
|
|
250
|
+
|
|
251
|
+
@media print {
|
|
252
|
+
body { background: #fff; font-size: 11.5pt; line-height: 1.5; }
|
|
253
|
+
.acoes { display: none !important; }
|
|
254
|
+
.folha {
|
|
255
|
+
max-width: none; margin: 0; padding: 0;
|
|
256
|
+
border: none; box-shadow: none; border-radius: 0;
|
|
257
|
+
}
|
|
258
|
+
.capa { break-after: avoid; }
|
|
259
|
+
.capa h1 { font-size: 24pt; }
|
|
260
|
+
dl.meta { background: #f7f8f9; break-inside: avoid; }
|
|
261
|
+
.sumario { break-inside: avoid; break-after: page; }
|
|
262
|
+
.corpo h1, .corpo h2, .corpo h3 { break-after: avoid; }
|
|
263
|
+
.corpo pre.bloco, .corpo blockquote, .corpo table, .anexo { break-inside: avoid; }
|
|
264
|
+
.corpo pre.bloco { background: #f4f5f7; color: #16181d; border: 1px solid var(--linha); }
|
|
265
|
+
.corpo a { color: inherit; text-decoration: underline; }
|
|
266
|
+
.rodape { break-inside: avoid; }
|
|
267
|
+
tr, li { break-inside: avoid; }
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
@media (max-width: 720px) {
|
|
271
|
+
.folha { padding: 32px 22px 44px; margin: 12px; }
|
|
272
|
+
.capa h1 { font-size: 26px; }
|
|
273
|
+
}
|
|
274
|
+
</style>
|
|
275
|
+
</head>
|
|
276
|
+
<body>
|
|
277
|
+
|
|
278
|
+
<div class="acoes" role="toolbar" aria-label="Ações do relatório">
|
|
279
|
+
<span class="id">${escapar(d.oc_id)}</span>
|
|
280
|
+
<button class="principal" onclick="window.print()" title="Imprimir ou salvar como PDF">
|
|
281
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
282
|
+
<path d="M4.5 6V2.5h7V6M4.5 12H3a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-1.5"/>
|
|
283
|
+
<rect x="4.5" y="10" width="7" height="3.5"/>
|
|
284
|
+
</svg>
|
|
285
|
+
Imprimir / PDF
|
|
286
|
+
</button>
|
|
287
|
+
<button onclick="baixarMd()" title="Baixar o arquivo Markdown original">
|
|
288
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
289
|
+
<path d="M8 2.5v7.5M5.2 7.4 8 10.2l2.8-2.8M2.8 12.4v1.1h10.4v-1.1"/>
|
|
290
|
+
</svg>
|
|
291
|
+
Baixar .md
|
|
292
|
+
</button>
|
|
293
|
+
</div>
|
|
294
|
+
|
|
295
|
+
<article class="folha">
|
|
296
|
+
<header class="capa">
|
|
297
|
+
<span class="selo">${escapar(rotulo)}</span>
|
|
298
|
+
<h1>${escapar(d.titulo)}</h1>
|
|
299
|
+
<p class="subtitulo">${SUBTITULO[d.tipo]}</p>
|
|
300
|
+
</header>
|
|
301
|
+
|
|
302
|
+
${metaHtml(d)}
|
|
303
|
+
${sumarioHtml(sumario)}
|
|
304
|
+
|
|
305
|
+
<div class="corpo">
|
|
306
|
+
${html}
|
|
307
|
+
</div>
|
|
308
|
+
|
|
309
|
+
${arquivosHtml(d)}
|
|
310
|
+
|
|
311
|
+
<footer class="rodape">
|
|
312
|
+
<span>${escapar(d.oc_id)} · ${escapar(rotulo)}</span>
|
|
313
|
+
<span>Gerado pelo expx-painel a partir de ${escapar(d.nomeArquivo)}</span>
|
|
314
|
+
</footer>
|
|
315
|
+
</article>
|
|
316
|
+
|
|
317
|
+
<script>
|
|
318
|
+
var MD_B64 = "${md}";
|
|
319
|
+
var NOME = ${literal(d.nomeArquivo)};
|
|
320
|
+
function baixarMd() {
|
|
321
|
+
try {
|
|
322
|
+
var bin = atob(MD_B64);
|
|
323
|
+
var bytes = new Uint8Array(bin.length);
|
|
324
|
+
for (var i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
|
325
|
+
var url = URL.createObjectURL(new Blob([bytes], { type: "text/markdown;charset=utf-8" }));
|
|
326
|
+
var a = document.createElement("a");
|
|
327
|
+
a.href = url; a.download = NOME; a.click();
|
|
328
|
+
setTimeout(function () { URL.revokeObjectURL(url); }, 1000);
|
|
329
|
+
} catch (e) {
|
|
330
|
+
alert("Não foi possível baixar o arquivo neste navegador.");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
document.title = ${literal(titulo)};
|
|
334
|
+
</script>
|
|
335
|
+
</body>
|
|
336
|
+
</html>`;
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=pagina.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagina.js","sourceRoot":"","sources":["../../src/relatorio/pagina.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Projeto } from "../parser/projeto/montar.js";
|
|
2
|
+
import { type Violacao } from "../parser/conformidade/regras.js";
|
|
3
|
+
/** O estado que o painel serve: o projeto lido do disco mais as violações derivadas. */
|
|
4
|
+
export type EstadoPainel = Projeto & {
|
|
5
|
+
violacoes: Violacao[];
|
|
6
|
+
};
|
|
7
|
+
export type OpcoesEstado = {
|
|
8
|
+
raiz: string;
|
|
9
|
+
diasBloqueio: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Relê o projeto inteiro do disco (decisão D-27). Releitura total, não
|
|
13
|
+
* incremental: as regras de conformidade cruzam referências entre arquivos,
|
|
14
|
+
* então uma visão parcial produziria violação falsa de referência quebrada.
|
|
15
|
+
*/
|
|
16
|
+
export declare function lerEstado(op: OpcoesEstado, agora?: Date): EstadoPainel;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { montarProjeto } from "../parser/projeto/montar.js";
|
|
2
|
+
import { verificarConformidade } from "../parser/conformidade/regras.js";
|
|
3
|
+
/**
|
|
4
|
+
* Relê o projeto inteiro do disco (decisão D-27). Releitura total, não
|
|
5
|
+
* incremental: as regras de conformidade cruzam referências entre arquivos,
|
|
6
|
+
* então uma visão parcial produziria violação falsa de referência quebrada.
|
|
7
|
+
*/
|
|
8
|
+
export function lerEstado(op, agora = new Date()) {
|
|
9
|
+
const projeto = montarProjeto(op.raiz, agora);
|
|
10
|
+
const violacoes = verificarConformidade(projeto, {
|
|
11
|
+
hoje: agora,
|
|
12
|
+
diasBloqueio: op.diasBloqueio,
|
|
13
|
+
});
|
|
14
|
+
return { ...projeto, violacoes };
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=estado.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estado.js","sourceRoot":"","sources":["../../src/servidor/estado.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAgB,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAiB,MAAM,kCAAkC,CAAC;AAUxF;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,EAAgB,EAAE,QAAc,IAAI,IAAI,EAAE;IAClE,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE;QAC/C,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,EAAE,CAAC,YAAY;KAC9B,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Server } from "node:http";
|
|
2
|
+
import { type EstadoPainel } from "./estado.js";
|
|
3
|
+
export type OpcoesServidor = {
|
|
4
|
+
raiz: string;
|
|
5
|
+
porta: number;
|
|
6
|
+
diasBloqueio?: number;
|
|
7
|
+
/** Pasta com o build da UI; quando ausente, só a API responde. */
|
|
8
|
+
estaticos?: string;
|
|
9
|
+
};
|
|
10
|
+
export type ServidorPainel = {
|
|
11
|
+
endereco: () => {
|
|
12
|
+
address: string;
|
|
13
|
+
port: number;
|
|
14
|
+
};
|
|
15
|
+
url: () => string;
|
|
16
|
+
estado: () => EstadoPainel;
|
|
17
|
+
recarregar: () => EstadoPainel;
|
|
18
|
+
aoAtualizar: (ouvinte: (e: EstadoPainel) => void) => void;
|
|
19
|
+
http: Server;
|
|
20
|
+
fechar: () => Promise<void>;
|
|
21
|
+
};
|
|
22
|
+
export declare function criarServidor(op: OpcoesServidor): Promise<ServidorPainel>;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { extname, join, normalize, resolve, sep } from "node:path";
|
|
4
|
+
import { lerEstado } from "./estado.js";
|
|
5
|
+
import { paginaRelatorio } from "../relatorio/pagina.js";
|
|
6
|
+
/**
|
|
7
|
+
* O servidor escuta EXCLUSIVAMENTE em 127.0.0.1.
|
|
8
|
+
*
|
|
9
|
+
* Isso não é preferência, é decisão de segurança: o painel lê a pasta de
|
|
10
|
+
* documentação de um projeto e a serve sem autenticação nenhuma. Expor isso
|
|
11
|
+
* na rede local entregaria o conteúdo a qualquer um no mesmo Wi-Fi. Não há
|
|
12
|
+
* flag, variável de ambiente ou opção que mude o bind.
|
|
13
|
+
*/
|
|
14
|
+
const HOST = "127.0.0.1";
|
|
15
|
+
const TIPOS = {
|
|
16
|
+
".html": "text/html; charset=utf-8",
|
|
17
|
+
".js": "text/javascript; charset=utf-8",
|
|
18
|
+
".css": "text/css; charset=utf-8",
|
|
19
|
+
".json": "application/json; charset=utf-8",
|
|
20
|
+
".svg": "image/svg+xml",
|
|
21
|
+
".ico": "image/x-icon",
|
|
22
|
+
};
|
|
23
|
+
function json(res, dados, status = 200) {
|
|
24
|
+
const corpo = JSON.stringify(dados, (_k, v) => (v instanceof Map ? undefined : v));
|
|
25
|
+
res.writeHead(status, {
|
|
26
|
+
"content-type": "application/json; charset=utf-8",
|
|
27
|
+
"cache-control": "no-store",
|
|
28
|
+
});
|
|
29
|
+
res.end(corpo);
|
|
30
|
+
}
|
|
31
|
+
export async function criarServidor(op) {
|
|
32
|
+
const diasBloqueio = op.diasBloqueio ?? 7;
|
|
33
|
+
let estado = lerEstado({ raiz: op.raiz, diasBloqueio });
|
|
34
|
+
const ouvintes = [];
|
|
35
|
+
function recarregar() {
|
|
36
|
+
estado = lerEstado({ raiz: op.raiz, diasBloqueio });
|
|
37
|
+
for (const o of ouvintes)
|
|
38
|
+
o(estado);
|
|
39
|
+
return estado;
|
|
40
|
+
}
|
|
41
|
+
const http = createServer((req, res) => {
|
|
42
|
+
// O painel é somente leitura: nenhum método além de GET é aceito.
|
|
43
|
+
if (req.method !== "GET") {
|
|
44
|
+
json(res, { erro: "o painel e somente leitura" }, 405);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const url = new URL(req.url ?? "/", `http://${HOST}`);
|
|
48
|
+
const caminho = url.pathname;
|
|
49
|
+
// Relatório em aba própria: /relatorio?oc=<id>&tipo=tecnico|uso
|
|
50
|
+
// e o .md original em /relatorio.md com os mesmos parâmetros.
|
|
51
|
+
if (caminho === "/relatorio" || caminho === "/relatorio.md") {
|
|
52
|
+
servirRelatorio(estado, url, caminho.endsWith(".md"), res);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
switch (caminho) {
|
|
56
|
+
case "/api/projeto":
|
|
57
|
+
json(res, estado);
|
|
58
|
+
return;
|
|
59
|
+
case "/api/conformidade":
|
|
60
|
+
json(res, { violacoes: estado.violacoes });
|
|
61
|
+
return;
|
|
62
|
+
case "/api/rejeicoes":
|
|
63
|
+
json(res, { rejeicoes: estado.rejeicoes });
|
|
64
|
+
return;
|
|
65
|
+
case "/api/historico":
|
|
66
|
+
json(res, { historico: estado.historico });
|
|
67
|
+
return;
|
|
68
|
+
case "/api/saude":
|
|
69
|
+
json(res, { ok: true, raiz: estado.raiz, lido_em: estado.lido_em });
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (op.estaticos) {
|
|
73
|
+
const servido = servirEstatico(op.estaticos, caminho, res);
|
|
74
|
+
if (servido)
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
|
|
78
|
+
res.end("nao encontrado");
|
|
79
|
+
});
|
|
80
|
+
await new Promise((ok) => http.listen(op.porta, HOST, ok));
|
|
81
|
+
const endereco = () => {
|
|
82
|
+
const e = http.address();
|
|
83
|
+
if (e === null || typeof e === "string")
|
|
84
|
+
return { address: HOST, port: op.porta };
|
|
85
|
+
return { address: e.address, port: e.port };
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
endereco,
|
|
89
|
+
url: () => `http://${HOST}:${String(endereco().port)}`,
|
|
90
|
+
estado: () => estado,
|
|
91
|
+
recarregar,
|
|
92
|
+
aoAtualizar: (o) => ouvintes.push(o),
|
|
93
|
+
http,
|
|
94
|
+
fechar: () => new Promise((ok) => {
|
|
95
|
+
http.closeAllConnections?.();
|
|
96
|
+
http.close(() => ok());
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Serve um relatório do histórico: como documento HTML pronto para impressão,
|
|
102
|
+
* ou como o .md original para download.
|
|
103
|
+
*
|
|
104
|
+
* O conteúdo vem do estado já lido — o servidor não volta ao disco aqui, então
|
|
105
|
+
* a página não pode escapar da pasta observada nem por parâmetro manipulado.
|
|
106
|
+
*/
|
|
107
|
+
function servirRelatorio(estado, url, comoMd, res) {
|
|
108
|
+
const oc = url.searchParams.get("oc");
|
|
109
|
+
const tipo = url.searchParams.get("tipo") === "uso" ? "uso" : "tecnico";
|
|
110
|
+
const entrada = estado.historico.find((h) => h.oc_id === oc);
|
|
111
|
+
const rel = entrada ? (tipo === "uso" ? entrada.uso : entrada.tecnico) : null;
|
|
112
|
+
if (!entrada || rel === null) {
|
|
113
|
+
res.writeHead(404, { "content-type": "text/html; charset=utf-8" });
|
|
114
|
+
res.end(`<!doctype html><meta charset="utf-8"><title>Relatorio nao encontrado</title>` +
|
|
115
|
+
`<body style="font:16px system-ui;padding:48px;color:#16181d">` +
|
|
116
|
+
`<h1 style="font-size:20px">Relatório não encontrado</h1>` +
|
|
117
|
+
`<p>Não há relatório <b>${tipo}</b> para a ocorrência informada.</p></body>`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const corpo = typeof rel["_corpo"] === "string" ? rel["_corpo"] : "";
|
|
121
|
+
const nomeArquivo = `${entrada.oc_id}-${tipo}.md`;
|
|
122
|
+
if (comoMd) {
|
|
123
|
+
res.writeHead(200, {
|
|
124
|
+
"content-type": "text/markdown; charset=utf-8",
|
|
125
|
+
"content-disposition": `attachment; filename="${nomeArquivo}"`,
|
|
126
|
+
"cache-control": "no-store",
|
|
127
|
+
});
|
|
128
|
+
res.end(corpo);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const dados = {
|
|
132
|
+
tipo,
|
|
133
|
+
titulo: rel["titulo"] ?? entrada.titulo,
|
|
134
|
+
oc_id: entrada.oc_id,
|
|
135
|
+
tipo_ocorrencia: rel["tipo_ocorrencia"] ?? entrada.tipo_ocorrencia,
|
|
136
|
+
fechado_em: rel["fechado_em"] ?? entrada.fechado_em,
|
|
137
|
+
modulo_afetado: rel["modulo_afetado"] ?? entrada.modulo_afetado,
|
|
138
|
+
corpo,
|
|
139
|
+
nomeArquivo,
|
|
140
|
+
...(tipo === "tecnico"
|
|
141
|
+
? {
|
|
142
|
+
arquivos_alterados: rel["arquivos_alterados"] ?? [],
|
|
143
|
+
testes_adicionados: rel["testes_adicionados"] ?? null,
|
|
144
|
+
}
|
|
145
|
+
: {}),
|
|
146
|
+
};
|
|
147
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
|
|
148
|
+
res.end(paginaRelatorio(dados));
|
|
149
|
+
}
|
|
150
|
+
/** Serve o build da UI, com fallback para index.html (rotas do cliente). */
|
|
151
|
+
function servirEstatico(raiz, caminho, res) {
|
|
152
|
+
const base = resolve(raiz);
|
|
153
|
+
const pedido = caminho === "/" ? "/index.html" : caminho;
|
|
154
|
+
// normaliza e confina: nenhum ../ escapa da pasta de estáticos
|
|
155
|
+
const alvo = resolve(join(base, normalize(pedido).replace(/^(\.\.[/\\])+/, "")));
|
|
156
|
+
const dentro = alvo === base || alvo.startsWith(base + sep);
|
|
157
|
+
const arquivo = dentro && existsSync(alvo) ? alvo : join(base, "index.html");
|
|
158
|
+
if (!existsSync(arquivo))
|
|
159
|
+
return false;
|
|
160
|
+
res.writeHead(200, { "content-type": TIPOS[extname(arquivo)] ?? "application/octet-stream" });
|
|
161
|
+
res.end(readFileSync(arquivo));
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/servidor/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type Observador = {
|
|
2
|
+
parar: () => Promise<void>;
|
|
3
|
+
};
|
|
4
|
+
/**
|
|
5
|
+
* Observa a pasta e agrupa alterações próximas num único disparo.
|
|
6
|
+
*
|
|
7
|
+
* O debounce não é só economia: as skills gravam `tasks.md` a cada transição
|
|
8
|
+
* de task, e ler o arquivo no instante da gravação produz YAML truncado —
|
|
9
|
+
* uma rejeição transitória que apareceria e sumiria da tela "fora do schema".
|
|
10
|
+
* Esperar o silêncio evita mostrar ao usuário um erro que não existe.
|
|
11
|
+
*/
|
|
12
|
+
export declare function observar(raiz: string, aoMudar: () => void, debounceMs?: number): Promise<Observador>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { watch } from "chokidar";
|
|
2
|
+
/**
|
|
3
|
+
* Observa a pasta e agrupa alterações próximas num único disparo.
|
|
4
|
+
*
|
|
5
|
+
* O debounce não é só economia: as skills gravam `tasks.md` a cada transição
|
|
6
|
+
* de task, e ler o arquivo no instante da gravação produz YAML truncado —
|
|
7
|
+
* uma rejeição transitória que apareceria e sumiria da tela "fora do schema".
|
|
8
|
+
* Esperar o silêncio evita mostrar ao usuário um erro que não existe.
|
|
9
|
+
*/
|
|
10
|
+
export async function observar(raiz, aoMudar, debounceMs = 300) {
|
|
11
|
+
let timer = null;
|
|
12
|
+
const agendar = () => {
|
|
13
|
+
if (timer)
|
|
14
|
+
clearTimeout(timer);
|
|
15
|
+
timer = setTimeout(() => {
|
|
16
|
+
timer = null;
|
|
17
|
+
aoMudar();
|
|
18
|
+
}, debounceMs);
|
|
19
|
+
};
|
|
20
|
+
const watcher = watch(raiz, {
|
|
21
|
+
ignoreInitial: true,
|
|
22
|
+
ignored: (caminho) => /(^|[/\\])(node_modules|\.git|dist)([/\\]|$)/.test(caminho),
|
|
23
|
+
awaitWriteFinish: { stabilityThreshold: Math.max(50, debounceMs / 3), pollInterval: 20 },
|
|
24
|
+
});
|
|
25
|
+
watcher.on("add", agendar).on("change", agendar).on("unlink", agendar).on("addDir", agendar).on("unlinkDir", agendar);
|
|
26
|
+
// erro de observação (permissão, limite de watchers) não derruba o painel
|
|
27
|
+
watcher.on("error", () => undefined);
|
|
28
|
+
await new Promise((ok) => watcher.on("ready", () => ok()));
|
|
29
|
+
return {
|
|
30
|
+
parar: async () => {
|
|
31
|
+
if (timer)
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
await watcher.close();
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=observador.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observador.js","sourceRoot":"","sources":["../../src/servidor/observador.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAkB,MAAM,UAAU,CAAC;AAMjD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAY,EACZ,OAAmB,EACnB,UAAU,GAAG,GAAG;IAEhB,IAAI,KAAK,GAA0B,IAAI,CAAC;IAExC,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QAC/B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,KAAK,GAAG,IAAI,CAAC;YACb,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,UAAU,CAAC,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,OAAO,GAAc,KAAK,CAAC,IAAI,EAAE;QACrC,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,6CAA6C,CAAC,IAAI,CAAC,OAAO,CAAC;QACzF,gBAAgB,EAAE,EAAE,kBAAkB,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE;KACzF,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACtH,0EAA0E;IAC1E,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAErC,MAAM,IAAI,OAAO,CAAO,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAEjE,OAAO;QACL,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { EstadoPainel } from "./estado.js";
|
|
2
|
+
export type OpcoesPainel = {
|
|
3
|
+
raiz: string;
|
|
4
|
+
porta: number;
|
|
5
|
+
diasBloqueio?: number;
|
|
6
|
+
debounceMs?: number;
|
|
7
|
+
estaticos?: string;
|
|
8
|
+
};
|
|
9
|
+
export type Painel = {
|
|
10
|
+
url: () => string;
|
|
11
|
+
urlWebsocket: () => string;
|
|
12
|
+
porta: () => number;
|
|
13
|
+
estado: () => EstadoPainel;
|
|
14
|
+
parar: () => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Junta servidor, observador e websocket.
|
|
18
|
+
*
|
|
19
|
+
* O websocket envia o ESTADO INTEIRO a cada atualização (decisão D-28), não
|
|
20
|
+
* um delta. O estado de um projeto documental é pequeno, e mandar tudo
|
|
21
|
+
* elimina a classe de bug em que servidor e tela discordam depois de uma
|
|
22
|
+
* mensagem perdida.
|
|
23
|
+
*/
|
|
24
|
+
export declare function iniciarPainel(op: OpcoesPainel): Promise<Painel>;
|