Skip to content

Commit e9591e9

Browse files
committed
update
1 parent 66dac15 commit e9591e9

11 files changed

Lines changed: 924 additions & 1 deletion

File tree

.github/workflows/pages.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Deploy Pages
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch: {}
8+
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: pages
16+
cancel-in-progress: true
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
25+
- name: Install dependencies
26+
run: |
27+
sudo apt-get update
28+
sudo apt-get install -y sqlite3 brotli
29+
30+
- name: Generate test database
31+
run: |
32+
ROWS=20000 PAYLOAD_SIZE=256 scripts/generate-test-db.sh data/source.sqlite
33+
34+
- name: Prepare database artifacts
35+
run: |
36+
DB_VERSION="${GITHUB_SHA}" \
37+
DB_URL=./data/db.sqlite.gz \
38+
DB_BROTLI_URL=./data/db.sqlite.br \
39+
scripts/prepare-db.sh data/source.sqlite
40+
41+
- name: Upload Pages artifact
42+
uses: actions/upload-pages-artifact@v3
43+
with:
44+
path: docs
45+
46+
deploy:
47+
needs: build
48+
runs-on: ubuntu-latest
49+
environment:
50+
name: github-pages
51+
url: ${{ steps.deployment.outputs.page_url }}
52+
steps:
53+
- name: Deploy to GitHub Pages
54+
id: deployment
55+
uses: actions/deploy-pages@v4
56+

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/data/*.sqlite
2+
/docs/data/manifest.json
3+
/docs/data/*.sqlite
4+
/docs/data/*.sqlite.gz
5+
/docs/data/*.sqlite.br
6+
/tmp/
7+

README.md

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,65 @@
1-
# sqliteWASMGithub
1+
# Site estático com SQLite + WASM no GitHub Pages
2+
3+
Este projeto mostra como publicar um site estático no GitHub Pages que baixa um banco SQLite grande, comprime em gzip/brotli, grava no navegador (OPFS/IndexedDB) e executa consultas localmente com SQLite WASM.
4+
5+
## Limites relevantes do GitHub Pages
6+
- Repositório e artefatos publicados: ~1 GB é o teto prático. Acima disso a publicação costuma falhar.
7+
- Arquivos individuais no Git: evite >100 MB. Para bancos >500 MB, publique o `.sqlite.gz` via GitHub Releases ou outro storage estático e aponte a URL no loader.
8+
- Builds automatizados (Pages Actions) têm janela curta (~10 min) e banda limitada. Prefira subir o arquivo já comprimido, sem etapas pesadas no CI.
9+
10+
## Estrutura
11+
- `docs/`: site servível pelo Pages.
12+
- `docs/data/`: manifest e (opcionalmente) o banco comprimido. Para arquivos grandes, use só um placeholder e referencie uma URL externa.
13+
- `docs/js/`: loader do banco e UI.
14+
- `docs/vendor/`: dependências de terceiros (pako). O wasm do SQLite é carregado de CDN por padrão.
15+
- `scripts/`: utilitários para preparar o banco.
16+
17+
## Fluxo resumido
18+
1) Gerar/atualizar o banco: `sqlite3 data/source.sqlite ".read migrations.sql"`, depois `scripts/prepare-db.sh`.
19+
2) Publicar o `.sqlite.gz` (recomendado via Releases) e atualizar `docs/data/manifest.json` com `version`, `url`, `size` e `sha256`.
20+
3) Rodar `scripts/serve.sh` para testar localmente (`http://localhost:8080`).
21+
4) Subir para o GitHub e habilitar Pages apontando para `docs/`.
22+
23+
## Workflow no GitHub Actions
24+
- O deploy do Pages gera os artefatos no CI (db comprimido + manifest).
25+
- Por isso os arquivos gerados localmente ficam no `.gitignore`:
26+
`data/source.sqlite`, `docs/data/db.sqlite.*`, `docs/data/manifest.json` e `tmp/`.
27+
- Para testes locais, gere com `scripts/generate-test-db.sh` e `scripts/prepare-db.sh`.
28+
29+
## Como gerar um banco de ~500 MB (sequencial)
30+
1) Gerar o banco grande de teste:
31+
```
32+
scripts/generate-test-db.sh
33+
```
34+
Opcional (ajustar tamanho):
35+
```
36+
ROWS=450000 PAYLOAD_SIZE=1024 scripts/generate-test-db.sh data/source.sqlite
37+
```
38+
Observações:
39+
- Execute os comandos a partir da raiz do projeto.
40+
- O banco de origem fica em `data/source.sqlite` (fora de `docs/`).
41+
- Os arquivos comprimidos e o `manifest.json` são gravados em `docs/data/`.
42+
43+
2) Compactar e gerar o manifest:
44+
```
45+
DB_VERSION=test-500mb \
46+
DB_URL=./data/db.sqlite.gz \
47+
DB_BROTLI_URL=./data/db.sqlite.br \
48+
scripts/prepare-db.sh data/source.sqlite
49+
```
50+
51+
3) Servir localmente:
52+
```
53+
scripts/serve.sh 8080
54+
```
55+
Abrir `http://localhost:8080` e executar uma query de teste:
56+
```
57+
SELECT id, nome, categoria, valor, length(payload) AS payload_len
58+
FROM items
59+
LIMIT 10;
60+
```
61+
62+
## Observações
63+
- Navegador precisa suportar WASM e, para streaming eficiente, `DecompressionStream` e OPFS. O loader possui fallback para pako + buffer em memória (menos ideal).
64+
- Mantenha consultas paginadas/limitadas na UI para evitar estouro de memória ao ler tabelas grandes.
65+

docs/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Guia rápido
2+
3+
Este diretório é publicado no GitHub Pages. Para testar localmente:
4+
5+
```bash
6+
scripts/serve.sh
7+
# abra http://localhost:8080
8+
```
9+
10+
## Manifest (`data/manifest.json`)
11+
- Campos esperados:
12+
- `version`: versão do dataset (ex.: `v1`).
13+
- `sources.gzip|brotli`: cada item tem `url`, `size`, `sha256`, `encoding`.
14+
- Dica: para arquivos >100 MB suba o `.sqlite.gz` em GitHub Releases e use a URL de download direto.
15+
16+
## Fluxo no navegador
17+
1. Faz `fetch` do manifest.
18+
2. Escolhe brotli (se disponível) ou gzip.
19+
3. Tenta stream + descompressão com `DecompressionStream` gravando no OPFS.
20+
4. Se OPFS/stream não estiver disponível, faz fallback para buffer em memória (menos eficiente).
21+
5. Abre o banco com `sql.js` (WASM) em modo read-only.
22+
23+
## Cache
24+
- Metadados ficam em `localStorage` (`sqlite.version`, `sqlite.file`, `sqlite.source`).
25+
- O arquivo fica no OPFS (quando suportado). Botão “Limpar cache local” remove ambos.
26+
27+
## Atualizando o banco
28+
1. Gere o banco e comprima com `scripts/prepare-db.sh` (usa gzip e brotli).
29+
2. Publique os artefatos em Releases ou em `docs/data/`.
30+
3. Atualize `docs/data/manifest.json` com URLs/sha/size.
31+
4. Suba para o GitHub e re-deploy do Pages.
32+

docs/css/style.css

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
:root {
2+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
3+
color: #0f172a;
4+
background: #f8fafc;
5+
}
6+
7+
body {
8+
margin: 0;
9+
padding: 0;
10+
}
11+
12+
.page {
13+
max-width: 1080px;
14+
margin: 0 auto;
15+
padding: 24px;
16+
}
17+
18+
h1 {
19+
margin: 0 0 16px;
20+
font-size: 26px;
21+
}
22+
23+
.panel {
24+
background: #fff;
25+
border: 1px solid #e2e8f0;
26+
border-radius: 8px;
27+
padding: 16px;
28+
margin-bottom: 16px;
29+
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06);
30+
}
31+
32+
label {
33+
display: block;
34+
margin-bottom: 8px;
35+
font-weight: 600;
36+
}
37+
38+
input[type="text"],
39+
input[type="number"],
40+
textarea {
41+
width: 100%;
42+
box-sizing: border-box;
43+
padding: 10px;
44+
border: 1px solid #cbd5e1;
45+
border-radius: 6px;
46+
font-size: 14px;
47+
}
48+
49+
textarea {
50+
min-height: 140px;
51+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
52+
}
53+
54+
.actions {
55+
display: flex;
56+
gap: 12px;
57+
flex-wrap: wrap;
58+
}
59+
60+
button {
61+
border: none;
62+
background: #2563eb;
63+
color: #fff;
64+
padding: 10px 14px;
65+
border-radius: 6px;
66+
font-weight: 600;
67+
cursor: pointer;
68+
transition: transform 120ms ease, box-shadow 120ms ease;
69+
}
70+
71+
button.secondary {
72+
background: #0f172a;
73+
}
74+
75+
button.danger {
76+
background: #dc2626;
77+
}
78+
79+
button:disabled {
80+
opacity: 0.6;
81+
cursor: not-allowed;
82+
}
83+
84+
table {
85+
width: 100%;
86+
border-collapse: collapse;
87+
margin-top: 12px;
88+
}
89+
90+
th,
91+
td {
92+
padding: 8px 10px;
93+
border: 1px solid #e2e8f0;
94+
font-size: 13px;
95+
text-align: left;
96+
}
97+
98+
th {
99+
background: #f1f5f9;
100+
font-weight: 700;
101+
}
102+
103+
#status {
104+
padding: 10px 12px;
105+
border-radius: 6px;
106+
font-weight: 600;
107+
margin-top: 8px;
108+
}
109+
110+
#status[data-type="info"] {
111+
color: #0f172a;
112+
background: #e0f2fe;
113+
}
114+
115+
#status[data-type="warn"] {
116+
color: #92400e;
117+
background: #fef3c7;
118+
}
119+
120+
#status[data-type="error"] {
121+
color: #991b1b;
122+
background: #fee2e2;
123+
}
124+
125+
#meta {
126+
color: #475569;
127+
font-size: 13px;
128+
margin-top: 6px;
129+
}
130+

docs/index.html

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<!DOCTYPE html>
2+
<html lang="pt-BR">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>SQLite WASM no GitHub Pages</title>
7+
<link rel="stylesheet" href="./css/style.css" />
8+
<!-- Pako é usado apenas como fallback quando DecompressionStream não está disponível -->
9+
<script src="https://cdn.jsdelivr.net/npm/pako@2.1.0/dist/pako.min.js"></script>
10+
<script type="module" src="./js/ui.js"></script>
11+
</head>
12+
<body>
13+
<div class="page">
14+
<h1>SQLite grande no GitHub Pages (WASM)</h1>
15+
16+
<div class="panel">
17+
<label for="manifest-url">Manifest URL (.json com URLs/sha):</label>
18+
<input id="manifest-url" type="text" value="./data/manifest.json" />
19+
20+
<label for="file-name">Nome do arquivo local (OPFS):</label>
21+
<input id="file-name" type="text" value="db.sqlite" />
22+
23+
<div class="actions" style="margin: 12px 0">
24+
<label>
25+
<input id="prefer-brotli" type="checkbox" checked />
26+
Preferir brotli
27+
</label>
28+
<label>
29+
<input id="force-download" type="checkbox" />
30+
Forçar re-download (ignorar cache/localStorage)
31+
</label>
32+
</div>
33+
34+
<div class="actions">
35+
<button id="btn-fetch">Baixar e abrir banco</button>
36+
<button id="btn-clear" class="danger" type="button">Limpar cache local</button>
37+
</div>
38+
<div id="status" data-type="info"></div>
39+
<div id="meta"></div>
40+
</div>
41+
42+
<div class="panel">
43+
<label for="sql">SQL (Ctrl+Enter executa):</label>
44+
<textarea id="sql">SELECT id, nome, categoria, valor, length(payload) AS payload_len FROM items LIMIT 10;</textarea>
45+
<div class="actions" style="align-items: flex-end; margin-top: 8px">
46+
<div style="flex: 1; min-width: 140px">
47+
<label for="limit">Limite de linhas</label>
48+
<input id="limit" type="number" value="200" min="1" />
49+
</div>
50+
<button id="btn-run" class="secondary" disabled>Executar</button>
51+
</div>
52+
</div>
53+
54+
<div class="panel">
55+
<h3>Resultados</h3>
56+
<table>
57+
<thead id="results-head"></thead>
58+
<tbody id="results-body"></tbody>
59+
</table>
60+
</div>
61+
62+
<div class="panel">
63+
<h3>Dicas para bancos grandes</h3>
64+
<ul>
65+
<li>Para >100 MB, publique o `.sqlite.gz` em Releases e referencie a URL pública (CDN do GitHub).</li>
66+
<li>Prefira gzip se precisar de compatibilidade máxima; brotli é mais eficiente mas menos suportado em streaming.</li>
67+
<li>Use `scripts/prepare-db.sh` para VACUUM e gerar manifest com sha/tamanho.</li>
68+
<li>Mantenha consultas paginadas (limite configurável acima) para não estourar memória.</li>
69+
<li>O loader tenta armazenar no OPFS; se indisponível, faz fallback para buffer em memória.</li>
70+
</ul>
71+
</div>
72+
</div>
73+
</body>
74+
</html>
75+

0 commit comments

Comments
 (0)