import fs from "node:fs" import path from "node:path" import crypto from "node:crypto" import { Level } from "level" export const PACK_DEFINITIONS = [ { sourceFile: "armes.json", outputFolder: "armes", type: "Item" }, { sourceFile: "armures.json", outputFolder: "armures", type: "Item" }, { sourceFile: "equipements.json", outputFolder: "equipements", type: "Item" }, { sourceFile: "pouvoirs-compagnie.json", outputFolder: "pouvoirs-compagnie", type: "Item" }, { sourceFile: "competences.json", outputFolder: "competences", type: "Item" }, { sourceFile: "races.json", outputFolder: "races", type: "Item" }, { sourceFile: "tribus.json", outputFolder: "tribus", type: "Item" }, { sourceFile: "metiers.json", outputFolder: "metiers", type: "Item" }, { sourceFile: "sortileges.json", outputFolder: "sortileges", type: "Item" }, ] function slugId(input) { const hash = crypto.createHash("sha256").update(input).digest() const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" let id = "" for (let index = 0; id.length < 16; index += 1) { id += alphabet[hash[index % hash.length] % alphabet.length] } return id } function toPackDocument(entry, index, { documentSystemId, documentSystemVersion, coreVersion, createdTime, lastModifiedBy = "Copilot", } = {}) { const docId = slugId(`${entry.type}:${entry.name}`) return { name: entry.name, type: entry.type, img: entry.img ?? "icons/svg/item-bag.svg", system: entry.system ?? {}, effects: Array.isArray(entry.effects) ? entry.effects : [], flags: entry.flags ?? {}, _stats: { systemId: documentSystemId, systemVersion: documentSystemVersion, coreVersion, createdTime, modifiedTime: createdTime, lastModifiedBy, compendiumSource: null, duplicateSource: null, exportSource: null, }, _id: docId, folder: null, sort: index * 1000, ownership: { default: 0, }, } } async function buildPack({ sourcePath, outputPath, type, documentSystemId, documentSystemVersion, coreVersion, createdTime, lastModifiedBy, }) { const source = JSON.parse(fs.readFileSync(sourcePath, "utf8")) if (!Array.isArray(source)) { throw new Error(`Pack source must be an array: ${sourcePath}`) } fs.rmSync(outputPath, { recursive: true, force: true }) fs.mkdirSync(outputPath, { recursive: true }) const db = new Level(outputPath, { valueEncoding: "utf8" }) try { await db.open() const batch = db.batch() source.forEach((entry, index) => { if (!entry.type) { throw new Error(`Missing document type in ${sourcePath}: ${entry.name}`) } const doc = toPackDocument(entry, index, { documentSystemId, documentSystemVersion, coreVersion, createdTime, lastModifiedBy, }) batch.put(`!items!${doc._id}`, JSON.stringify(doc)) }) await batch.write() } finally { await db.close() } } export async function buildPacks({ sourceRoot, outputRoot, packDefinitions = PACK_DEFINITIONS, documentSystemId, documentSystemVersion, coreVersion, createdTime = Date.now(), lastModifiedBy = "Copilot", }) { for (const pack of packDefinitions) { await buildPack({ sourcePath: path.join(sourceRoot, pack.sourceFile), outputPath: path.join(outputRoot, pack.outputFolder), type: pack.type, documentSystemId, documentSystemVersion, coreVersion, createdTime, lastModifiedBy, }) } }