Added migration to the new parenting schema
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
|
||||
export default function cleanAt2(archive) {
|
||||
export default function cleanArchiveAtCurrent(archive) {
|
||||
archive.properties = archive.properties.map(prop => {
|
||||
let cleanProp = prop;
|
||||
try {
|
||||
@@ -1,6 +1,7 @@
|
||||
import migrateTo1 from './migrateArchiveTo1';
|
||||
import migrate1To2 from './migrateArchive1To2';
|
||||
import cleanAt2 from './cleanArchiveAt2';
|
||||
import migrate2To3 from './migrateArchive2To3';
|
||||
import cleanAtCurrent from './cleanArchiveAtCurrent';
|
||||
|
||||
/* eslint no-fallthrough: "off" -- Using switch fallthrough to run all
|
||||
migration steps after the current version of the file. */
|
||||
@@ -15,7 +16,9 @@ export default function migrateArchive(archive) {
|
||||
migrate1To2(archive);
|
||||
// V2 of DiceCloud, Schema version 2
|
||||
case 2:
|
||||
cleanAt2(archive);
|
||||
migrate2To3(archive);
|
||||
case 3:
|
||||
cleanAtCurrent(archive);
|
||||
break;
|
||||
default:
|
||||
throw 'Archive version not supported';
|
||||
|
||||
16
app/imports/migrations/archive/migrateArchive2To3.js
Normal file
16
app/imports/migrations/archive/migrateArchive2To3.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export default function migrate2To3(archive) {
|
||||
archive.properties = archive.properties.map(prop => {
|
||||
try {
|
||||
prop.root = prop.ancestors[0];
|
||||
if (!prop.root) {
|
||||
throw 'Property has no root ancestor, will become orphaned'
|
||||
}
|
||||
if (prop.parent?.collection === 'creatureProperties') {
|
||||
prop.parentId = prop.parent.id;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Property migration 2 -> 3 failed: ', { propId: prop._id, error: e.message || e.reason || e.toString() });
|
||||
}
|
||||
return prop;
|
||||
});
|
||||
}
|
||||
69
app/imports/migrations/server/dbv3/dbv3.test.ts
Normal file
69
app/imports/migrations/server/dbv3/dbv3.test.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { migrateCollection } from './dbv3'
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import { assert } from 'chai';
|
||||
|
||||
describe('dbv3 Migrate parenting structure', function () {
|
||||
// We are going to be adding malformed docs to the collection, so allow any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const collection = CreatureProperties as Mongo.Collection<any>;
|
||||
|
||||
this.beforeAll(async function () {
|
||||
// Add only the required properties
|
||||
await collection.removeAsync({});
|
||||
// Add a property and a child as if they were in schema v2
|
||||
// Use raw collection to bypass all schemas and validation
|
||||
await collection.rawCollection().insertMany([
|
||||
{
|
||||
'_id': 'classId',
|
||||
'type': 'class',
|
||||
'parent': { 'collection': 'creatures', 'id': 'creatureId' },
|
||||
'ancestors': [
|
||||
{ 'collection': 'creatures', 'id': 'creatureId' }
|
||||
],
|
||||
'order': 0,
|
||||
'tags': [],
|
||||
}, {
|
||||
'_id': 'noteId',
|
||||
'type': 'note',
|
||||
'parent': { 'collection': 'creatureProperties', 'id': 'classId' },
|
||||
'ancestors': [
|
||||
{ 'collection': 'creatures', 'id': 'creatureId' },
|
||||
{ 'collection': 'creatureProperties', 'id': 'classId' }
|
||||
],
|
||||
'order': 1,
|
||||
'tags': [],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
this.afterAll(async function () {
|
||||
// Remove all the properties
|
||||
await collection.removeAsync({});
|
||||
});
|
||||
|
||||
it('Migrates parenting to the new schema', async function () {
|
||||
// Migrate the collection
|
||||
await migrateCollection('creatureProperties');
|
||||
|
||||
// Get the new documents
|
||||
const parentDoc = await collection.findOneAsync('classId');
|
||||
const childDoc = await collection.findOneAsync('noteId');
|
||||
|
||||
assert.deepEqual(
|
||||
parentDoc.root, { collection: 'creatures', id: 'creatureId' },
|
||||
'parent root should be the creature'
|
||||
);
|
||||
assert.deepEqual(
|
||||
childDoc.root, { collection: 'creatures', id: 'creatureId' },
|
||||
'child root should be the creature'
|
||||
);
|
||||
|
||||
assert.doesNotHaveAnyKeys(parentDoc, ['parentId'], 'Parent should not have parentId set');
|
||||
assert.equal(childDoc.parentId, 'classId', 'child parentId should match parent\'s id');
|
||||
|
||||
assert.equal(parentDoc.left, 0, 'Parent left should be its old order');
|
||||
assert.equal(childDoc.left, 1, 'Child left should be its old order');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
48
app/imports/migrations/server/dbv3/dbv3.ts
Normal file
48
app/imports/migrations/server/dbv3/dbv3.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Migrations } from 'meteor/percolate:migrations';
|
||||
|
||||
// Git version 2.0.59
|
||||
// Database version 3
|
||||
Migrations.add({
|
||||
version: 3,
|
||||
name: 'Separates creature property tags from library tags',
|
||||
|
||||
up() {
|
||||
console.log('migrating up library nodes 2 -> 3');
|
||||
migrateCollection('libraryNodes');
|
||||
console.log('migrating up creature props 2 -> 3');
|
||||
migrateCollection('creatureProperties');
|
||||
console.log('New schema fields added, if it was done correctly remove the old fields manually');
|
||||
},
|
||||
|
||||
down() {
|
||||
throw 'Migrating from version 3 down to version 2 is not supported'
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export function migrateCollection(collectionName: string) {
|
||||
// @ts-expect-error Collection.get is not defined
|
||||
const collection = Mongo.Collection.get(collectionName);
|
||||
// Copy the parent id field and the root ancestor to the new structure
|
||||
// Using the mongo aggregation API
|
||||
return collection.rawCollection().updateMany({}, [
|
||||
{
|
||||
$addFields: {
|
||||
'root': { $arrayElemAt: ['$ancestors', 0] },
|
||||
'parentId': {
|
||||
// Parent ID must refer to a document in the same collection, so remove the parent ID
|
||||
// if the parent reference refers to a different collection
|
||||
$cond: {
|
||||
if: { $eq: [collectionName, '$parent.collection'] },
|
||||
then: '$parent.id',
|
||||
else: '$$REMOVE',
|
||||
}
|
||||
},
|
||||
// Set left and right to current order so that order is maintained on the first re-build
|
||||
// of the tree structure
|
||||
'left': '$order',
|
||||
'right': '$order',
|
||||
}
|
||||
},
|
||||
]);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dicecloud",
|
||||
"version": "2.0.57",
|
||||
"version": "2.0.59",
|
||||
"description": "Unofficial Online Realtime D&D 5e App",
|
||||
"license": "GPL-3.0",
|
||||
"repository": {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"preserveSymlinks": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"outDir": "build",
|
||||
"paths": {
|
||||
"/*": [
|
||||
"./*"
|
||||
|
||||
Reference in New Issue
Block a user