@paroicms/cli
Version:
CLI of ParoiCMS
260 lines • 9.77 kB
JavaScript
import { pathExists } from "@paroicms/internal-server-lib";
import { readFile, readdir, rename, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { packageDir } from "../context.js";
export async function migrateFrom1To2(directory, siteSchema) {
const lib = await loadCommonSchemaLibV1();
const l10n = {};
for (const language of siteSchema.languages) {
const l10nFile = join(directory, `site-schema.l10n.${language}.json`);
const obj = (await pathExists(l10nFile))
? JSON.parse(migrateRawL10n(await readFile(l10nFile, "utf-8")))
: {};
l10n[language] = obj;
}
const migrating = {
siteSchema,
l10n,
};
const { useModules, usedLibTypes } = convertUseModules(siteSchema.useModules, lib);
if (useModules) {
migrateUseModules(useModules);
}
siteSchema.useModules = useModules;
const documentTypes = [];
for (const documentType of siteSchema.documentTypes ?? []) {
if (typeof documentType === "string")
continue;
migrateDocumentType(documentType);
documentTypes.push(documentType);
}
siteSchema.documentTypes = documentTypes.length > 0 ? documentTypes : undefined;
const partTypes = [];
for (const partType of siteSchema.partTypes ?? []) {
if (typeof partType === "string")
continue;
migratePartType(partType);
partTypes.push(partType);
}
siteSchema.partTypes = partTypes.length > 0 ? partTypes : undefined;
while (true) {
const hasNew = importDependentTypes(migrating, usedLibTypes);
if (!hasNew)
break;
}
const { schemaEngineVersion, ...rest } = siteSchema;
const newSchema = { version: "2.0", ...rest };
await rename(join(directory, "site-schema.json"), join(directory, "site-schema-v1.json"));
await writeFile(join(directory, "site-schema.json"), JSON.stringify(newSchema, undefined, 2));
for (const language of siteSchema.languages) {
const obj = l10n[language];
if (!obj)
throw new Error(`L10n for language "${language}" not found`);
cleanObjectPropertyIfEmpty(obj, "documentTypes");
cleanObjectPropertyIfEmpty(obj, "partTypes");
const l10nFile = join(directory, `site-schema.l10n.${language}.json`);
if (await pathExists(l10nFile)) {
await rename(l10nFile, join(directory, `site-schema-v1.l10n.${language}.json`));
}
if (Object.keys(obj).length > 0) {
await writeFile(join(directory, `site-schema.l10n.${language}.json`), JSON.stringify(obj, undefined, 2));
}
}
return newSchema;
}
function cleanObjectPropertyIfEmpty(obj, propName) {
if (obj[propName] && Object.keys(obj[propName]).length === 0) {
obj[propName] = undefined;
}
}
function importDependentTypes(migrating, usedLibTypes) {
const { siteSchema, l10n } = migrating;
let hasNew = false;
const newDocumentTypes = [];
const newPartTypes = [];
for (const documentType of siteSchema.documentTypes ?? []) {
for (const typeName of getDependentDocumentTypeNames(documentType)) {
if (siteSchema.documentTypes?.find((t) => t.leafType === typeName) ||
newDocumentTypes.find((t) => t.leafType === typeName)) {
continue;
}
const newType = usedLibTypes.documentTypes[typeName];
if (!newType)
throw new Error(`Document type "${typeName}" not found`);
newDocumentTypes.push(newType);
importDependentDocumentL10n(l10n, usedLibTypes, typeName);
}
for (const partName of getDependenPartTypeNames(documentType)) {
if (siteSchema.partTypes?.find((t) => t.leafType === partName) ||
newPartTypes.find((t) => t.leafType === partName)) {
continue;
}
const newType = usedLibTypes.partTypes[partName];
if (!newType)
throw new Error(`Part type "${partName}" not found`);
newPartTypes.push(newType);
importDependentPartL10n(l10n, usedLibTypes, partName);
}
}
if (newDocumentTypes.length > 0) {
hasNew = true;
if (!siteSchema.documentTypes) {
siteSchema.documentTypes = [];
}
siteSchema.documentTypes.push(...newDocumentTypes);
}
if (newPartTypes.length > 0) {
hasNew = true;
if (!siteSchema.partTypes) {
siteSchema.partTypes = [];
}
siteSchema.partTypes.push(...newPartTypes);
}
return hasNew;
}
function importDependentDocumentL10n(l10n, usedLibTypes, documentTypeName) {
for (const language of Object.keys(usedLibTypes.l10n)) {
l10n[language] ??= {};
l10n[language].documentTypes ??= {};
const l10nDocumentTypes = l10n[language].documentTypes;
if (l10nDocumentTypes[documentTypeName])
continue;
l10nDocumentTypes[documentTypeName] =
usedLibTypes.l10n[language]?.documentTypes?.[documentTypeName];
}
}
function importDependentPartL10n(l10n, usedLibTypes, partTypeName) {
for (const language of Object.keys(usedLibTypes.l10n)) {
l10n[language] ??= {};
l10n[language].partTypes ??= {};
const l10nPartTypes = l10n[language].partTypes;
if (l10nPartTypes[partTypeName])
continue;
l10nPartTypes[partTypeName] = usedLibTypes.l10n[language]?.partTypes?.[partTypeName];
}
}
function getDependentDocumentTypeNames(documentType) {
return (documentType.labeling ?? []).reduce((acc, item) => {
acc.push(item.taxonomy);
return acc;
}, documentType.children ?? []);
}
function getDependenPartTypeNames(documentType) {
return (documentType.lists ?? []).reduce((acc, list) => {
acc.push(...list.parts);
return acc;
}, []);
}
function convertUseModules(oldUseModules, lib) {
const usedLibTypes = {
documentTypes: {},
partTypes: {},
l10n: {},
moduleNames: new Set(),
};
if (!oldUseModules)
return { useModules: undefined, usedLibTypes };
const useModules = [];
for (const moduleName of oldUseModules) {
const module = lib.get(moduleName);
if (!module) {
useModules.push(moduleName);
}
else {
prepareUseModules(module, lib, usedLibTypes);
}
}
return {
useModules: useModules.length > 0 ? useModules : undefined,
usedLibTypes,
};
}
function prepareUseModules(module, lib, usedLibTypes) {
if (usedLibTypes.moduleNames.has(module.name))
return;
usedLibTypes.moduleNames.add(module.name);
for (const documentType of module.schema.documentTypes ?? []) {
usedLibTypes.documentTypes[documentType.leafType] = documentType;
}
for (const partType of module.schema.partTypes ?? []) {
usedLibTypes.partTypes[partType.leafType] = partType;
}
for (const language of Object.keys(module.l10n)) {
usedLibTypes.l10n[language] = {
...usedLibTypes.l10n[language],
...module.l10n[language],
};
}
for (const moduleName of module.schema.useModules ?? []) {
const subModule = lib.get(moduleName);
if (!subModule)
throw new Error(`Module "${moduleName}" not found`);
prepareUseModules(subModule, lib, usedLibTypes);
}
}
async function loadCommonSchemaLibV1() {
const dir = join(packageDir, "site-schema-lib-v1");
const lib = new Map();
const entries = await readdir(dir);
for (const entry of entries) {
if (!entry.endsWith("site-schema.json"))
continue;
const libName = entry.substring(0, entry.length - "site-schema.json".length - 1);
lib.set(libName, {
name: libName,
schema: JSON.parse(await readFile(join(dir, entry), "utf-8")),
l10n: {
en: JSON.parse(await readFile(join(dir, `${libName}.site-schema.l10n.en.json`), "utf-8")),
fr: JSON.parse(await readFile(join(dir, `${libName}.site-schema.l10n.fr.json`), "utf-8")),
},
});
}
return lib;
}
function migrateUseModules(useModules) {
for (let i = 0; i < useModules.length; ++i) {
const moduleName = useModules[i];
if (moduleName === "media-policies") {
useModules[i] = "default-media-policies";
}
if (moduleName === "fields") {
useModules[i] = "field-lib";
}
}
}
function migrateDocumentType(documentType) {
if (documentType.withData !== undefined) {
if (!documentType.withData) {
documentType.redirectTo = "parent";
}
documentType.withData = undefined;
}
if (documentType.childOrdering) {
documentType.orderChildrenBy = documentType.childOrdering;
documentType.childOrdering = undefined;
}
if (documentType.lists) {
for (const list of documentType.lists) {
if (list.partLeafTypes) {
list.parts = list.partLeafTypes;
list.partLeafTypes = undefined;
}
if (list.partLimit) {
list.limit = list.partLimit;
list.partLimit = undefined;
}
}
}
}
function migratePartType(partType) {
if (partType.withData !== undefined) {
partType.withData = undefined;
}
}
function migrateRawL10n(raw) {
return raw
.replace(/addBtn/g, "addChild")
.replace(/addChildBtn/g, "addChild")
.replace(/addSectionBtn/g, "addPart");
}
//# sourceMappingURL=site-schema-migration-1-to-2.js.map