a67c18d691
Poprawki punktowe (niskiego ryzyka, z fallbackiem na v11/v12):
- greyknights/auto-loadout: pochodzenie z paczki przez _stats.compendiumSource
(flags.core.sourceId deprecated od v12)
- greyknights/gk-glow-toggle: canvas.perception.update -> płaska flaga
refreshLighting (stary format {lighting:{refresh}} nie działa od v11)
- greyknights/helpers: TextEditor -> foundry.applications.ux.TextEditor;
game.ui -> ui (martwy no-op)
- greyknights/ui-gkpanel: scene control tool v13 onClick -> onChange
- voidships-builder/voidships: loadTemplates -> foundry.applications.handlebars
- voidships-builder/voidship-actor: Actors -> foundry.documents.collections.Actors
- usunięto śmieciowe packs/*.db.bak
Skrypt help_scripts/pack_nedb_to_leveldb.mjs: przepakowuje kompendia NeDB(.db)
-> LevelDB (wymagane w v11+/v13/v14), czyta paczki z module.json, domyślnie
dry-run. Wykrywa też rozbieżność: gk-greyknights i wg-voidships-journal mają
w manifeście ścieżkę bez .db, a na dysku plik NeDB.
Nie ruszano vendored investigation-board (do aktualizacji z upstreamu).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
151 lines
5.4 KiB
JavaScript
Executable File
151 lines
5.4 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
// pack_nedb_to_leveldb.mjs
|
|
// Przepakowuje kompendia z legacy NeDB (.db, jeden JSON/linia) do formatu LevelDB
|
|
// (katalog), którego wymaga Foundry VTT v11+ (i v13/v14). Czyta listę paczek
|
|
// wprost z module.json danego modułu, więc nie trzeba niczego wpisywać ręcznie.
|
|
//
|
|
// Wymaga jednorazowo: npm i -D @foundryvtt/foundryvtt-cli (lub -g)
|
|
//
|
|
// Użycie:
|
|
// node help_scripts/pack_nedb_to_leveldb.mjs [--write] [--replace] [ścieżki/do/modułów...]
|
|
//
|
|
// (bez argumentów ścieżek) -> domyślnie 3 własne moduły w tym repo
|
|
// --write faktycznie buduje katalogi LevelDB (bez tego: tylko dry-run/plan)
|
|
// --replace po udanym zbudowaniu usuwa stary plik .db ORAZ podmienia ścieżkę
|
|
// w module.json (packs[].path: "packs/foo.db" -> "packs/foo")
|
|
//
|
|
// Bezpiecznie: domyślnie nic nie nadpisuje. LevelDB trafia obok, do packs/<name>.
|
|
// Stare .db zostają, dopóki nie podasz --replace.
|
|
|
|
import { readFile, writeFile, rm, mkdtemp, mkdir } from "node:fs/promises";
|
|
import { existsSync, statSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { fileURLToPath } from "node:url";
|
|
import path from "node:path";
|
|
|
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
const REPO = path.resolve(HERE, "..");
|
|
|
|
const args = process.argv.slice(2);
|
|
const WRITE = args.includes("--write");
|
|
const REPLACE = args.includes("--replace");
|
|
const moduleDirs = args.filter((a) => !a.startsWith("--"));
|
|
|
|
const DEFAULT_MODULES = [
|
|
"wg-greyknights",
|
|
"wg-voidships-builder",
|
|
"wg-voidships-journal",
|
|
].map((m) => path.join(REPO, m));
|
|
|
|
const targets = (moduleDirs.length ? moduleDirs : DEFAULT_MODULES).map((p) =>
|
|
path.resolve(p)
|
|
);
|
|
|
|
// Typ paczki z module.json -> documentType wymagany przez CLI dla źródła NeDB.
|
|
const TYPE_OK = new Set([
|
|
"Actor", "Item", "JournalEntry", "RollTable", "Macro",
|
|
"Scene", "Playlist", "Cards", "Adventure",
|
|
]);
|
|
|
|
async function loadCli() {
|
|
try {
|
|
return await import("@foundryvtt/foundryvtt-cli");
|
|
} catch {
|
|
console.error(
|
|
"\n[!] Brak @foundryvtt/foundryvtt-cli. Zainstaluj jednorazowo:\n" +
|
|
" npm i -D @foundryvtt/foundryvtt-cli\n"
|
|
);
|
|
process.exit(2);
|
|
}
|
|
}
|
|
|
|
async function processModule(cli, modDir) {
|
|
const manifestPath = path.join(modDir, "module.json");
|
|
if (!existsSync(manifestPath)) {
|
|
console.warn(`- pomijam ${modDir} (brak module.json)`);
|
|
return;
|
|
}
|
|
const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
const packs = manifest.packs ?? [];
|
|
if (!packs.length) {
|
|
console.log(`- ${manifest.id ?? path.basename(modDir)}: brak paczek`);
|
|
return;
|
|
}
|
|
|
|
let manifestDirty = false;
|
|
console.log(`\n=== ${manifest.id ?? path.basename(modDir)} ===`);
|
|
|
|
for (const pack of packs) {
|
|
const rel = pack.path; // np. "packs/wg-voidship-hulls.db" LUB "packs/gk-items"
|
|
const newRel = rel.replace(/\.db$/, ""); // docelowa ścieżka LevelDB (bez .db)
|
|
const outDir = path.join(modDir, newRel);
|
|
// Plik NeDB może być tam, gdzie wskazuje manifest (….db) albo obok, gdy
|
|
// manifest podaje ścieżkę bez rozszerzenia, a na dysku i tak leży <path>.db.
|
|
const nedbAbs = rel.endsWith(".db")
|
|
? path.join(modDir, rel)
|
|
: path.join(modDir, rel + ".db");
|
|
|
|
if (existsSync(outDir) && statSync(outDir).isDirectory() && !existsSync(nedbAbs)) {
|
|
console.log(` • ${pack.name}: już LevelDB (${newRel}/) — pomijam`);
|
|
continue;
|
|
}
|
|
if (!existsSync(nedbAbs) || !statSync(nedbAbs).isFile()) {
|
|
console.warn(` • ${pack.name}: nie znaleziono źródła NeDB (${path.relative(modDir, nedbAbs)}) — pomijam`);
|
|
continue;
|
|
}
|
|
if (rel === newRel) {
|
|
// manifest już wskazuje bez .db, ale plik to NeDB -> rozbieżność do naprawy
|
|
console.log(` (uwaga: module.json wskazuje "${rel}", a na dysku jest NeDB "${path.basename(nedbAbs)}")`);
|
|
}
|
|
const type = pack.type;
|
|
if (!TYPE_OK.has(type)) {
|
|
console.warn(` • ${pack.name}: nieznany type="${type}" — pomijam`);
|
|
continue;
|
|
}
|
|
const abs = nedbAbs;
|
|
console.log(
|
|
` • ${pack.name} [${type}] ${rel} -> ${newRel}/ ${WRITE ? "" : "(dry-run)"}`
|
|
);
|
|
if (!WRITE) continue;
|
|
|
|
// 1) NeDB -> katalog źródeł (.json z poprawnymi _key)
|
|
const srcTmp = await mkdtemp(path.join(tmpdir(), "fvtt-src-"));
|
|
await cli.extractPack(abs, srcTmp, {
|
|
nedb: true,
|
|
documentType: type,
|
|
yaml: false,
|
|
log: false,
|
|
});
|
|
// 2) źródła -> LevelDB
|
|
await mkdir(outDir, { recursive: true });
|
|
await cli.compilePack(srcTmp, outDir, { yaml: false, log: false });
|
|
await rm(srcTmp, { recursive: true, force: true });
|
|
console.log(` ✓ zbudowano LevelDB: ${newRel}/`);
|
|
|
|
if (REPLACE) {
|
|
await rm(abs, { force: true });
|
|
if (pack.path !== newRel) {
|
|
pack.path = newRel;
|
|
manifestDirty = true;
|
|
}
|
|
console.log(
|
|
` ✓ usunięto ${path.basename(abs)}` +
|
|
(manifestDirty ? ", zaktualizowano ścieżkę w module.json" : "")
|
|
);
|
|
}
|
|
}
|
|
|
|
if (manifestDirty && WRITE && REPLACE) {
|
|
await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
|
|
}
|
|
}
|
|
|
|
const cli = WRITE ? await loadCli() : null; // CLI potrzebny tylko do budowania
|
|
console.log(
|
|
WRITE
|
|
? `Przepakowuję (${REPLACE ? "z podmianą .db i module.json" : "obok, .db zostają"})`
|
|
: "DRY-RUN — plan (dodaj --write aby zbudować, --replace aby podmienić):"
|
|
);
|
|
for (const t of targets) await processModule(cli, t);
|
|
console.log("\nGotowe.");
|