UNPKG

@paroicms/server

Version:
190 lines 8.28 kB
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