177 lines
4.8 KiB
JavaScript
177 lines
4.8 KiB
JavaScript
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { logger } from "../utils/logger.js";
|
|
import { getGame } from "../utils/utils.js";
|
|
|
|
/**
|
|
* @template T
|
|
* @typedef {(document: T) => Promise<void>} Migrator
|
|
*/
|
|
|
|
/**
|
|
* Migrate a collection.
|
|
* @template T
|
|
* @param {WorldCollection} collection
|
|
* @param {Migrator<T>} migrateDocument
|
|
* @returns {Promise<import("./migration.js").Result>} A promise that resolves once the migration is complete
|
|
*/
|
|
export async function migrateCollection(collection, migrateDocument) {
|
|
/** @type {import("./migration.js").Result} */
|
|
let result = "success";
|
|
const { documentName } = collection.constructor;
|
|
for (const document of collection) {
|
|
logger.info(`Migrating ${documentName} document ${document.name} (${document.id})`);
|
|
try {
|
|
await migrateDocument(document);
|
|
} catch (err) {
|
|
logger.error(
|
|
`Error during migration of ${documentName} document ${document.name} (${document.id}), continuing anyways.`,
|
|
err,
|
|
);
|
|
result = "error";
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @param {Migrator<ActiveEffect>} [migrateActiveEffect]
|
|
* @returns {Migrator<Scene>}
|
|
*/
|
|
export function getItemMigrator(migrateActiveEffect) {
|
|
/**
|
|
* @param {Item} item
|
|
*/
|
|
return async (item) => {
|
|
if (migrateActiveEffect) {
|
|
for (const effect of item.effects) {
|
|
await migrateActiveEffect(effect);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {Migrator<Item>} [migrateItem]
|
|
* @param {Migrator<ActiveEffect>} [migrateActiveEffect]
|
|
* @returns {Migrator<Scene>}
|
|
*/
|
|
export function getActorMigrator(migrateItem, migrateActiveEffect) {
|
|
/**
|
|
* @param {Actor} actor
|
|
*/
|
|
return async (actor) => {
|
|
if (migrateItem) {
|
|
for (const item of actor.items) {
|
|
await migrateItem(item);
|
|
}
|
|
}
|
|
if (migrateActiveEffect) {
|
|
for (const effect of actor.effects) {
|
|
await migrateActiveEffect(effect);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {Migrator<Actor>} [migrateActor]
|
|
* @returns {Migrator<Scene>}
|
|
*/
|
|
export function getSceneMigrator(migrateActor) {
|
|
/**
|
|
* @param {Scene} scene
|
|
*/
|
|
return async (scene) => {
|
|
if (migrateActor) {
|
|
for (const token of scene.tokens) {
|
|
if (!token.actorLink && token.actor) {
|
|
await migrateActor(token.actor);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/** @typedef {(pack: CompendiumCollection) => Promise<import("./migration.js").Result>} CompendiumMigrator */
|
|
|
|
/**
|
|
* Migrate world compendium packs.
|
|
* @param {CompendiumMigrator} migrateCompendium A function for migrating a single compendium pack
|
|
* @returns {Promise<import("./migration.js").Result>} A promise that resolves once the migration is complete
|
|
*/
|
|
export async function migrateCompendiums(migrateCompendium) {
|
|
/** @type {import("./migration.js").Result} */
|
|
let result = "success";
|
|
for (const compendium of getGame().packs ?? []) {
|
|
if (compendium.metadata.package !== "world") continue;
|
|
if (!["Actor", "Item", "Scene"].includes(compendium.metadata.type)) continue;
|
|
const r = await migrateCompendium(compendium);
|
|
if (r === "error") {
|
|
result = "error";
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @typedef {object} Migrators
|
|
* @property {Migrator<Item>} [migrateItem]
|
|
* @property {Migrator<Actor>} [migrateActor]
|
|
* @property {Migrator<Scene>} [migrateScene]
|
|
*/
|
|
|
|
/**
|
|
* Get a compendium migrator for the given migrators.
|
|
* @param {Migrators} [migrators={}] The functions to use for getting update data
|
|
* @param {{migrateToTemplateEarly?: boolean}} [options={}] Additional options for the compendium migrator
|
|
* @returns {CompendiumMigrator} The resulting compendium migrator
|
|
*/
|
|
export function getCompendiumMigrator(
|
|
{ migrateItem, migrateActor, migrateScene } = {},
|
|
{ migrateToTemplateEarly = true } = {},
|
|
) {
|
|
return async (pack) => {
|
|
/** @type {import("./migration.js").Result} */
|
|
let result = "success";
|
|
|
|
const type = pack.metadata.type;
|
|
const migrateDocument = {
|
|
Item: migrateItem,
|
|
Actor: migrateActor,
|
|
Scene: migrateScene,
|
|
}[type];
|
|
|
|
if (migrateDocument) {
|
|
const wasLocked = pack.locked;
|
|
await pack.configure({ locked: false });
|
|
if (migrateToTemplateEarly) {
|
|
await pack.migrate();
|
|
}
|
|
|
|
const documents = await pack.getDocuments();
|
|
|
|
for (const doc of documents) {
|
|
try {
|
|
logger.info(`Migrating document ${doc.name} (${doc.id}) in compendium ${pack.collection}`);
|
|
await migrateDocument(doc);
|
|
} catch (err) {
|
|
logger.error(
|
|
`Error during migration of document ${doc.name} (${doc.id}) in compendium ${pack.collection}, continuing anyways.`,
|
|
err,
|
|
);
|
|
result = "error";
|
|
}
|
|
}
|
|
|
|
if (!migrateToTemplateEarly) {
|
|
await pack.migrate();
|
|
}
|
|
await pack.configure({ locked: wasLocked });
|
|
}
|
|
|
|
return result;
|
|
};
|
|
}
|