Captura integral do acervo da Brasiliana Fotográfica (Biblioteca Nacional) para s3://brasiliana: 13.060 itens, 12.985 com imagem de preservação, 13.059 com miniatura derivada, 2.137 cópias legadas e 636 posts do blog. 41.444 objetos no ledger. Os 75 itens sem preservação estão em errors.md: a página do item responde 200, mas a origem serve o bitstream com HTTP 500. Nenhum fica fora do mural, porque todos têm thumbnail. Não versionado, por viver no bucket ou ser reconstruível: catálogo, posts .jsonl, atlas .webp, sqlite de estado e logs. Credenciais ficam de fora pelo .gitignore.
63 lines
2.4 KiB
JavaScript
63 lines
2.4 KiB
JavaScript
// reprojeta-meta-mapa.mjs — reescreve SÓ o `meta` de cada item do
|
|
// web/atlas/atlas-map.json a partir do pipeline/catalogo.jsonl, sem re-renderizar
|
|
// os atlas .webp (posições, cores e recortes das peças ficam intactos).
|
|
//
|
|
// Use quando as regras de metadados do web/build-atlas.js mudarem e não valer a
|
|
// pena reconstruir 47 MB de imagem. As regras aqui têm de espelhar as de
|
|
// summarize()/pickAll() lá — em 2026-09-12 as duas foram escritas juntas.
|
|
//
|
|
// node pipeline/reprojeta-meta-mapa.mjs (da raiz do projeto)
|
|
import fs from 'node:fs';
|
|
import readline from 'node:readline';
|
|
|
|
const MAP = 'web/atlas/atlas-map.json';
|
|
const pickAll = (item, field, noUrls) => {
|
|
const out = [];
|
|
for (const row of item.full_table || []) {
|
|
if (row.field !== field) continue;
|
|
const v = String(row.value ?? '').trim();
|
|
if (!v || out.includes(v)) continue;
|
|
if (noUrls && /^https?:\/\//i.test(v)) continue;
|
|
out.push(v);
|
|
}
|
|
return out;
|
|
};
|
|
const some = (i, f, noUrls) => { const v = pickAll(i, f, noUrls); return v.length ? v : undefined; };
|
|
const one = (i, f) => pickAll(i, f)[0] || undefined;
|
|
|
|
const d = JSON.parse(fs.readFileSync(MAP, 'utf8'));
|
|
const wanted = new Set(Object.keys(d.map));
|
|
const extra = new Map();
|
|
|
|
const rl = readline.createInterface({ input: fs.createReadStream('pipeline/catalogo.jsonl'), crlfDelay: Infinity });
|
|
for await (const line of rl) {
|
|
if (!line.trim()) continue;
|
|
const o = JSON.parse(line);
|
|
if (!wanted.has(o.handle)) continue;
|
|
extra.set(o.handle, {
|
|
subject: some(o, 'dc.subject'),
|
|
description: some(o, 'dc.description'),
|
|
coverage: some(o, 'dc.coverage'),
|
|
source: one(o, 'dc.source'),
|
|
publisher: one(o, 'dc.publisher'),
|
|
relation: some(o, 'dc.relation', true),
|
|
identifier: some(o, 'dc.identifier', true),
|
|
});
|
|
}
|
|
|
|
let enriched = 0, missing = 0;
|
|
for (const [h, e] of Object.entries(d.map)) {
|
|
const add = extra.get(h);
|
|
if (!add) { missing++; continue; }
|
|
let touched = false;
|
|
for (const [k, v] of Object.entries(add)) if (v !== undefined) { e.meta[k] = v; touched = true; }
|
|
// deriváveis da chave: não repetir (ver build-atlas.js)
|
|
delete e.meta.handle;
|
|
delete e.meta.source_url;
|
|
if (touched) enriched++;
|
|
}
|
|
const out = JSON.stringify(d);
|
|
fs.writeFileSync(MAP, out);
|
|
console.log(`itens: ${wanted.size} | enriquecidos: ${enriched} | sem registro: ${missing}`);
|
|
console.log(`atlas-map.json: ${(out.length / 1048576).toFixed(2)} MB`);
|