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 => {
|
archive.properties = archive.properties.map(prop => {
|
||||||
let cleanProp = prop;
|
let cleanProp = prop;
|
||||||
try {
|
try {
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import migrateTo1 from './migrateArchiveTo1';
|
import migrateTo1 from './migrateArchiveTo1';
|
||||||
import migrate1To2 from './migrateArchive1To2';
|
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
|
/* eslint no-fallthrough: "off" -- Using switch fallthrough to run all
|
||||||
migration steps after the current version of the file. */
|
migration steps after the current version of the file. */
|
||||||
@@ -15,7 +16,9 @@ export default function migrateArchive(archive) {
|
|||||||
migrate1To2(archive);
|
migrate1To2(archive);
|
||||||
// V2 of DiceCloud, Schema version 2
|
// V2 of DiceCloud, Schema version 2
|
||||||
case 2:
|
case 2:
|
||||||
cleanAt2(archive);
|
migrate2To3(archive);
|
||||||
|
case 3:
|
||||||
|
cleanAtCurrent(archive);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw 'Archive version not supported';
|
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",
|
"name": "dicecloud",
|
||||||
"version": "2.0.57",
|
"version": "2.0.59",
|
||||||
"description": "Unofficial Online Realtime D&D 5e App",
|
"description": "Unofficial Online Realtime D&D 5e App",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"preserveSymlinks": true,
|
"preserveSymlinks": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
|
"outDir": "build",
|
||||||
"paths": {
|
"paths": {
|
||||||
"/*": [
|
"/*": [
|
||||||
"./*"
|
"./*"
|
||||||
|
|||||||
Reference in New Issue
Block a user