@paroicms/server
Version:
The ParoiCMS server
190 lines • 8.28 kB
JavaScript
import { setMetadataDbSchemaVersion } from "@paroicms/internal-server-lib";
import { type } from "arktype";
import { mainDbSchemaName, mainDbSchemaVersion } from "./db-constants.js";
export async function migrateMainDb(cn, { fromVersion, logger }) {
const toVersion = mainDbSchemaVersion;
let currentVersion = fromVersion;
if (currentVersion === 6) {
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 7 });
currentVersion = 7;
}
if (currentVersion === 7) {
await cn.raw(`create table PaOrderedLeaf (
leafId integer not null primary key references PaLeaf (id) on delete cascade,
orderNum integer not null
)`);
await cn.raw(`create table PaPartLeaf (
leafId integer not null primary key references PaLeaf (id) on delete cascade,
listName varchar(100) not null,
documentLeafId integer not null references PaLeaf (id)
)`);
await cn.raw(`insert into PaOrderedLeaf (leafId, orderNum)
select leafId, itemNum from PaLeafItem`);
await cn.raw(`insert into PaPartLeaf (leafId, listName, documentLeafId)
select i.leafId, i.listName, l.parentId
from PaLeafItem i
inner join PaLeaf l on l.id = i.leafId`);
await cn.raw("drop table PaLeafItem");
await cn.raw("alter table PaTermFlag rename column flaggedId to labeledId");
await cn.raw("alter table PaTermFlag rename to PaLabeling");
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 8 });
currentVersion = 8;
}
if (currentVersion === 8) {
await cn.raw("alter table PaLeaf rename column leafType to typeName");
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 9 });
currentVersion = 9;
}
if (currentVersion === 9) {
await cn.raw("alter table PaLeaf rename to PaNode");
await cn.raw("drop index if exists PaLeaf_typeName_idx");
await cn.raw("drop index if exists PaLeaf_leafType_idx");
await cn.raw("create index PaNode_typeName_idx on PaNode (typeName)");
await cn.raw("alter table PaOrderedLeaf rename to PaOrderedNode");
await cn.raw("alter table PaOrderedNode rename column leafId to nodeId");
await cn.raw("alter table PaPartLeaf rename to PaPartNode");
await cn.raw("alter table PaPartNode rename column leafId to nodeId");
await cn.raw("alter table PaPartNode rename column documentLeafId to documentNodeId");
await cn.raw("drop index if exists PaPartLeaf_listName_idx");
await cn.raw("create index PaPartNode_listName_idx on PaPartNode (listName)");
await cn.raw("alter table PaSection rename to PaNodel");
await cn.raw("alter table PaNodel rename column leafId to nodeId");
await cn.raw("alter table PaNodel rename column lang to language");
await cn.raw("alter table PaDocument rename column leafId to nodeId");
await cn.raw("alter table PaDocument rename column lang to language");
await cn.raw("alter table PaFieldVarchar rename column leafId to nodeId");
await cn.raw("alter table PaFieldVarchar rename column lang to language");
await cn.raw("alter table PaFieldText rename column leafId to nodeId");
await cn.raw("alter table PaFieldText rename column lang to language");
await cn.raw("update PaPartNode set listName = '_subParts' where listName = 'subParts'");
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 10 });
currentVersion = 10;
}
if (currentVersion === 10) {
await cn.raw(`create table PaFieldLabeling (
field varchar(100) not null,
nodeId integer not null references PaNode (id) on delete cascade,
termId integer not null references PaNode (id),
orderNum integer,
primary key (field, nodeId, termId)
)`);
await cn.raw(`insert into PaFieldLabeling (field, nodeId, termId)
select tax.typeName, PaLabeling.labeledId, PaLabeling.termId
from PaLabeling
join PaNode term on term.id = PaLabeling.termId
join PaNode tax on tax.id = term.parentId`);
await cn.raw("drop table PaLabeling");
await cn.raw(`update PaFieldText set dataType = 'json' where dataType = 'quillDelta'`);
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 11 });
currentVersion = 11;
}
if (currentVersion === 11) {
await migrateAllQuillDeltaFieldsFrom11to12(cn, logger);
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 12 });
currentVersion = 12;
}
if (currentVersion === 12) {
await cn.raw("alter table PaNodel rename to PaLNode");
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 13 });
currentVersion = 13;
}
if (currentVersion === 13) {
await cn.raw("update PaFieldVarchar set field = 'buttonLabel' where field = 'shortTitle'");
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 14 });
currentVersion = 14;
}
if (currentVersion === 14) {
await cn.raw("ALTER TABLE PaNode DROP COLUMN depth");
await setMetadataDbSchemaVersion(cn, { dbSchemaName: mainDbSchemaName, value: 15 });
currentVersion = 15;
}
if (currentVersion !== toVersion) {
throw new Error(`version of ${mainDbSchemaName} database should be '${toVersion}', but is '${currentVersion}'`);
}
logger.info(`${mainDbSchemaName} database was migrated from ${fromVersion} to ${currentVersion}`);
}
async function migrateAllQuillDeltaFieldsFrom11to12(cn, logger) {
let count = 0;
const rows = await cn("PaFieldText")
.select("field", "nodeId", "language", "val")
.where("dataType", "json")
.whereNotNull("val");
const RowAT = type({
field: "string",
nodeId: "number",
language: "string",
val: "string",
"+": "reject",
}).pipe((r) => ({
...r,
nodeId: String(r.nodeId),
}));
for (const row of rows) {
let fieldValue;
try {
const validatedRow = RowAT.assert(row);
fieldValue = {
...validatedRow,
val: JSON.parse(validatedRow.val),
};
}
catch (error) {
logger.error(`Error parsing JSON for field "${row.field}" on nodeId ${row.nodeId} in language "${row.language}"`, error);
continue;
}
const newVal = migrateQuillDeltaFrom11to12(fieldValue.val, logger);
if (newVal) {
await cn("PaFieldText")
.update({ val: JSON.stringify(newVal) })
.where({
field: fieldValue.field,
nodeId: fieldValue.nodeId,
language: fieldValue.language,
});
++count;
}
}
if (count > 0) {
logger.info(`Migrated ${count} quill delta field(s) in ${mainDbSchemaName} database`);
}
}
function migrateQuillDeltaFrom11to12(delta, logger) {
if (!delta?.ops || !Array.isArray(delta.ops))
return;
const { ops } = delta;
let modified = false;
const newOps = ops
.map((op) => {
if (!op.insert || typeof op.insert !== "object")
return op;
if (Object.keys(op.insert).length !== 1)
return op;
if (!op.insert.img || typeof op.insert.img !== "object")
return op;
const { uid, align, variant, zoom, href } = op.insert.img;
if (!uid || !align || !variant) {
logger.warn(`Quill Delta migration, remove incomplete image: ${JSON.stringify(op.insert)}`);
modified = true;
return;
}
const { insert, ...opRest } = op;
modified = true;
return {
insert: {
media: {
mediaId: uid,
resizeRule: variant,
align,
zoomable: zoom === "none" ? undefined : true,
href: href,
},
},
...opRest,
};
})
.filter(Boolean);
if (modified) {
return { ops: newOps };
}
}
//# sourceMappingURL=ddl-migration.js.map