@agility/cli
Version:
Agility CLI for working with your content. (Public Beta)
433 lines • 29.1 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processPage = processPage;
var ansi_colors_1 = __importDefault(require("ansi-colors"));
var content_item_mapper_1 = require("lib/mappers/content-item-mapper");
var template_mapper_1 = require("lib/mappers/template-mapper"); // Internal helper function to process a single page
var translate_zone_names_1 = require("./translate-zone-names");
var find_page_in_other_locale_1 = require("./find-page-in-other-locale");
function processPage(_a) {
return __awaiter(this, arguments, void 0, function (_b) {
var existingPage, channelID, templateMapper, targetTemplate, templateRef, pageMapping, mappingToOtherLocale, sitemap, websiteChannel, hasTargetChanged, hasSourceChanged, isConflict, updateRequired, createRequired, pageTypeDisplay, sourceUrl, targetUrl, sourceZones, mappedZones, contentIdsToValidate, _i, _c, _d, zoneName, zoneModules, _e, zoneModules_1, module_1, sourceContentId, contentMapper_1, _f, _g, _h, zoneName, zoneModules, newZoneContent, _j, zoneModules_2, module_2, newModule, sourceContentId, targetContentID, targetContentId, mappingResults_1, foundMappings_1, missingMappings_1, totalModules, isLegitimateEmptyPage, originalZones, originalModuleCount, _k, _l, _m, zoneName, zoneModules, formattedZones, pageTitle, pageJSON, pageCopy, payload, parentIDArg, mapping, placeBeforeIDArg, mapping, pageIDInOtherLocale, otherLocale, savePageResponse, finalContentIds_1, batchID, _o, pollBatchUntilComplete, extractBatchResults, completedBatch, _p, batchSuccessItems, batchFailedItems, actualPageID, savedPageVersionID, createdPageData, pageTypeDisplay_1, error_1;
var _q, _r;
var channel = _b.channel, page = _b.page, sourceGuid = _b.sourceGuid, targetGuid = _b.targetGuid, locale = _b.locale, apiClient = _b.apiClient, _s = _b.overwrite, overwrite = _s === void 0 ? false : _s, _t = _b.insertBeforePageId, insertBeforePageId = _t === void 0 ? null : _t, pageMapper = _b.pageMapper, parentPageID = _b.parentPageID, logger = _b.logger;
return __generator(this, function (_u) {
switch (_u.label) {
case 0:
existingPage = null;
channelID = -1;
templateMapper = new template_mapper_1.TemplateMapper(sourceGuid, targetGuid);
_u.label = 1;
case 1:
_u.trys.push([1, 10, , 11]);
targetTemplate = null;
// Only try to find template mapping for non-folder pages
if (page.pageType !== "folder" && page.templateName) {
templateRef = templateMapper.getTemplateMappingByPageTemplateName(page.templateName, 'source');
if (!templateRef) {
logger.page.error(page, "Missing page template ".concat(page.templateName, " in source data, skipping"), locale, channel, targetGuid);
return [2 /*return*/, "skip"];
}
targetTemplate = templateMapper.getMappedEntity(templateRef, 'target');
}
pageMapping = pageMapper.getPageMapping(page, 'source');
existingPage = pageMapper.getMappedEntity(pageMapping, 'target');
mappingToOtherLocale = null;
if (!!existingPage) return [3 /*break*/, 3];
return [4 /*yield*/, (0, find_page_in_other_locale_1.findPageInOtherLocale)({
sourcePageID: page.pageID,
locale: locale,
sourceGuid: sourceGuid,
targetGuid: targetGuid
})];
case 2:
//check the other locales to see if this page has been mapped in another locale
mappingToOtherLocale = _u.sent();
_u.label = 3;
case 3: return [4 /*yield*/, apiClient.pageMethods.getSitemap(targetGuid, locale)];
case 4:
sitemap = _u.sent();
websiteChannel = sitemap === null || sitemap === void 0 ? void 0 : sitemap.find(function (channelObj) { return channelObj.name.toLowerCase() === channel.toLowerCase(); });
if (websiteChannel) {
channelID = websiteChannel.digitalChannelID;
}
else {
channelID = ((_q = sitemap === null || sitemap === void 0 ? void 0 : sitemap[0]) === null || _q === void 0 ? void 0 : _q.digitalChannelID) || 1; // Fallback to first channel or default
}
hasTargetChanged = pageMapper.hasTargetChanged(existingPage);
hasSourceChanged = pageMapper.hasSourceChanged(page);
isConflict = hasTargetChanged && hasSourceChanged;
updateRequired = (hasSourceChanged && !isConflict) || overwrite;
createRequired = !existingPage;
pageTypeDisplay = {
static: "Page",
link: "Link",
folder: "Folder",
}[page.pageType] || page.pageType;
if (isConflict) {
sourceUrl = "https://app.agilitycms.com/instance/".concat(sourceGuid, "/").concat(locale, "/pages/").concat(page.pageID);
targetUrl = "https://app.agilitycms.com/instance/".concat(targetGuid, "/").concat(locale, "/pages/").concat(existingPage.pageID);
console.warn("\u26A0\uFE0F Conflict detected ".concat(pageTypeDisplay, " ").concat(ansi_colors_1.default.underline(page.name), " ").concat(ansi_colors_1.default.bold.grey("changes detected in both source and target"), ". Please resolve manually."));
console.warn(" - Source: ".concat(sourceUrl));
console.warn(" - Target: ".concat(targetUrl));
}
else if (createRequired) {
//CREATE NEW PAGE - nothing to do here yet...
}
else if (!updateRequired) {
// Add to reference mapper for future lookups
if (existingPage) {
pageMapper.addMapping(page, existingPage);
}
logger.page.skipped(page, "up to date, skipping", locale, channel, targetGuid);
return [2 /*return*/, "skip"]; // Skip processing - page already exists
}
sourceZones = page.zones ? __assign({}, page.zones) : {};
mappedZones = (0, translate_zone_names_1.translateZoneNames)(sourceZones, targetTemplate);
contentIdsToValidate = [];
for (_i = 0, _c = Object.entries(mappedZones); _i < _c.length; _i++) {
_d = _c[_i], zoneName = _d[0], zoneModules = _d[1];
if (Array.isArray(zoneModules)) {
for (_e = 0, zoneModules_1 = zoneModules; _e < zoneModules_1.length; _e++) {
module_1 = zoneModules_1[_e];
if (module_1.item && typeof module_1.item === "object") {
sourceContentId = module_1.item.contentid || module_1.item.contentId;
if (sourceContentId && sourceContentId > 0) {
contentIdsToValidate.push(sourceContentId);
}
}
}
}
}
contentMapper_1 = new content_item_mapper_1.ContentItemMapper(sourceGuid, targetGuid, locale);
for (_f = 0, _g = Object.entries(mappedZones); _f < _g.length; _f++) {
_h = _g[_f], zoneName = _h[0], zoneModules = _h[1];
newZoneContent = [];
if (Array.isArray(zoneModules)) {
for (_j = 0, zoneModules_2 = zoneModules; _j < zoneModules_2.length; _j++) {
module_2 = zoneModules_2[_j];
newModule = __assign({}, module_2);
// Check if module has content item reference
if (module_2.item && typeof module_2.item === "object") {
sourceContentId = module_2.item.contentid || module_2.item.contentId;
if (sourceContentId && sourceContentId > 0) {
targetContentID = contentMapper_1.getContentItemMappingByContentID(sourceContentId, 'source').targetContentID;
if (targetContentID) {
targetContentId = targetContentID;
newModule.item = __assign(__assign({}, module_2.item), { contentid: targetContentId, fulllist: module_2.item.fulllist });
// Remove contentId field to avoid confusion
delete newModule.item.contentId;
newZoneContent.push(newModule);
}
else {
// Content mapping failed - log detailed debug info for troubleshooting
console.error("\u274C No content mapping found for ".concat(module_2.module, ": contentID ").concat(sourceContentId, " in page ").concat(page.name));
// const contentMappings = contentMapper.getRecordsByType("content");
// console.log("Page", JSON.stringify(page, null, 2));
// console.error(`Total content mappings available: ${contentMappings.length}`);
// const allContentRecords = pageMapper.getRecordsByType("content");
// const matchingRecord = allContentRecords.find((r) => r.source.contentID === sourceContentId);
// if (matchingRecord) {
// console.error(`Found matching source record but issue with target:`, {
// sourceID: matchingRecord.source.contentID,
// targetID: matchingRecord.target?.contentID,
// hasTarget: !!matchingRecord.target,
// });
// } else {
// console.error(`No record found with source contentID: ${sourceContentId}`);
// }
}
}
else {
// Module without content reference - keep it
newZoneContent.push(newModule);
}
}
else {
// Module without content reference - keep it
newZoneContent.push(newModule);
}
}
}
mappedZones[zoneName] = newZoneContent;
}
// Content mapping validation - check which mappings were successful
if (contentIdsToValidate.length > 0) {
mappingResults_1 = {};
foundMappings_1 = 0;
missingMappings_1 = 0;
contentIdsToValidate.forEach(function (sourceContentId) {
var targetContentID = contentMapper_1.getContentItemMappingByContentID(sourceContentId, 'source').targetContentID;
if (targetContentID) {
mappingResults_1[sourceContentId] = {
found: true,
targetId: targetContentID,
};
foundMappings_1++;
}
else {
mappingResults_1[sourceContentId] = {
found: false,
error: targetContentID ? "Invalid target ID" : "No mapping found",
};
missingMappings_1++;
}
});
if (missingMappings_1 > 0) {
console.error(ansi_colors_1.default.bgRed("\u2717 Page \"".concat(page.name, "\" failed - ").concat(missingMappings_1, "/").concat(contentIdsToValidate.length, " missing content mappings")));
return [2 /*return*/, "failure"];
}
}
totalModules = Object.values(mappedZones).reduce(function (sum, zone) {
return sum + (Array.isArray(zone) ? zone.length : 0);
}, 0);
isLegitimateEmptyPage = function (page) {
// Folder pages don't have content modules
if (page.pageType === "folder")
return true;
// Link pages don't have content modules - they redirect to other URLs/pages/files
if (page.pageType === "link")
return true;
// Dynamic pages don't have modules in zones - their content comes from dynamic containers
// Check for dynamic page indicators
var pageAny = page;
if (pageAny.dynamic && pageAny.dynamic.referenceName)
return true;
if (pageAny.dynamicPageContentViewReferenceName)
return true;
// Pages with redirect URLs are link pages (even if pageType isn't explicitly 'link')
// Check for common redirect URL properties (using 'any' type to access properties safely)
if (pageAny.redirectUrl && pageAny.redirectUrl.trim())
return true;
if (pageAny.redirect && pageAny.redirect.url && pageAny.redirect.url.trim())
return true;
// Pages that link to files or other pages don't need modules
// Using safe property access since these may not be in the type definition
if (pageAny.linkToFileID && pageAny.linkToFileID > 0)
return true;
if (pageAny.linkToPageID && pageAny.linkToPageID > 0)
return true;
if (pageAny.linkToFile && pageAny.linkToFile > 0)
return true;
if (pageAny.linkToPage && pageAny.linkToPage > 0)
return true;
return false;
};
// Check if page has any content left after filtering
if (totalModules === 0) {
originalZones = page.zones || {};
originalModuleCount = 0;
for (_k = 0, _l = Object.entries(originalZones); _k < _l.length; _k++) {
_m = _l[_k], zoneName = _m[0], zoneModules = _m[1];
if (Array.isArray(zoneModules)) {
originalModuleCount += zoneModules.length;
}
}
// If the page originally had modules but now has none, that's a problem
// If it never had modules, that's fine (folder pages, etc.)
if (originalModuleCount > 0 && !existingPage && !isLegitimateEmptyPage(page)) {
console.error("\u2717 Page \"".concat(page.name, "\" lost all ").concat(originalModuleCount, " modules during content mapping"));
return [2 /*return*/, "failure"];
}
}
formattedZones = mappedZones && typeof mappedZones === "object" ? mappedZones : {};
pageTitle = page.title || page.menuText || page.name || "Untitled Page";
pageJSON = JSON.stringify(page, null, 2);
pageCopy = JSON.parse(pageJSON);
payload = __assign(__assign({}, pageCopy), { pageID: existingPage ? existingPage.pageID : -1, title: pageTitle, channelID: channelID, zones: formattedZones,
// CRITICAL: Include path field from sitemap enrichment (API bug: target sitemap returns null paths)
path: page.path || "" });
parentIDArg = -1;
if (parentPageID && parentPageID > 0) {
mapping = pageMapper.getPageMappingByPageID(parentPageID, 'source');
if (((mapping === null || mapping === void 0 ? void 0 : mapping.targetPageID) || 0) > 0) {
parentIDArg = mapping.targetPageID;
payload.parentPageID = mapping.targetPageID;
}
else {
parentIDArg = -1;
payload.parentPageID = -1; // No parent
}
}
else {
payload.parentPageID = -1; // Ensure no parent
}
placeBeforeIDArg = -1;
if (insertBeforePageId && insertBeforePageId > 0) {
mapping = pageMapper.getPageMappingByPageID(insertBeforePageId, 'source');
if (((mapping === null || mapping === void 0 ? void 0 : mapping.targetPageID) || 0) > 0) {
placeBeforeIDArg = mapping.targetPageID;
}
}
pageIDInOtherLocale = mappingToOtherLocale ? mappingToOtherLocale.PageIDOtherLanguage : -1;
otherLocale = mappingToOtherLocale ? mappingToOtherLocale.OtherLanguageCode : null;
return [4 /*yield*/, apiClient.pageMethods.savePage(payload, targetGuid, locale, parentIDArg, placeBeforeIDArg, true, pageIDInOtherLocale, otherLocale)];
case 5:
savePageResponse = _u.sent();
if (!(Array.isArray(savePageResponse) && savePageResponse.length > 0)) return [3 /*break*/, 8];
finalContentIds_1 = [];
Object.values(payload.zones || {}).forEach(function (zone) {
if (Array.isArray(zone)) {
zone.forEach(function (module) {
var _a;
if ((_a = module.item) === null || _a === void 0 ? void 0 : _a.contentid) {
finalContentIds_1.push(module.item.contentid);
}
});
}
});
batchID = savePageResponse[0];
return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("../batch-polling")); })];
case 6:
_o = _u.sent(), pollBatchUntilComplete = _o.pollBatchUntilComplete, extractBatchResults = _o.extractBatchResults;
return [4 /*yield*/, pollBatchUntilComplete(apiClient, batchID, targetGuid, [payload], // Pass payload for FIFO error matching
300, // maxAttempts
2000, // intervalMs
"Page" // batchType
)];
case 7:
completedBatch = _u.sent();
_p = extractBatchResults(completedBatch, [page]), batchSuccessItems = _p.successfulItems, batchFailedItems = _p.failedItems;
actualPageID = -1;
savedPageVersionID = -1;
if (batchSuccessItems.length > 0) {
//grab the save page info form the batch success items
actualPageID = batchSuccessItems[0].newId;
savedPageVersionID = ((_r = batchSuccessItems[0].newItem) === null || _r === void 0 ? void 0 : _r.processedItemVersionID) || -1;
}
else if (batchFailedItems.length > 0) {
logger.page.error(page, "\u2717 Page ".concat(page.name, " batch failed: ").concat(batchFailedItems[0].error), locale, channel, targetGuid);
}
if (actualPageID > 0) {
createdPageData = __assign(__assign({}, payload), { pageID: actualPageID });
if (savedPageVersionID > 0) {
// Set version ID if available
createdPageData.properties.versionID = savedPageVersionID; // Set version ID from batch result
}
pageMapper.addMapping(page, createdPageData); // Use original page for source key
pageTypeDisplay_1 = {
static: "Page",
link: "Link",
folder: "Folder",
}[page.pageType] || page.pageType;
if (existingPage) {
if (overwrite) {
logger.page.updated(page, "updated", locale, channel, targetGuid);
}
else {
logger.page.updated(page, "updated", locale, channel, targetGuid);
}
}
else {
logger.page.created(page, "created", locale, channel, targetGuid);
}
return [2 /*return*/, "success"]; // Success
}
else {
// Show errorData if available, otherwise generic failure
if (completedBatch.errorData && completedBatch.errorData.trim()) {
logger.page.error(page, "\u2717 Page \"".concat(page.name, "\" failed - ").concat(completedBatch.errorData, ", locale:").concat(locale), locale, channel, targetGuid);
}
else {
logger.page.error(page, "\u2717 Page \"".concat(page.name, "\" failed - invalid page ID: ").concat(actualPageID, ", locale:").concat(locale), locale, channel, targetGuid);
}
return [2 /*return*/, "failure"];
}
return [3 /*break*/, 9];
case 8:
logger.page.error(page, "\u2717 Page \"".concat(page.name, "\" failed in locale:").concat(locale, " - unexpected response format"), locale, channel, targetGuid);
return [2 /*return*/, "failure"]; // Failure
case 9: return [3 /*break*/, 11];
case 10:
error_1 = _u.sent();
logger.page.error(page, "\u2717 Page \"".concat(page.name, "\" failed in locale:").concat(locale, " - ").concat(error_1.message), locale, channel, targetGuid);
return [2 /*return*/, "failure"]; // Failure
case 11: return [2 /*return*/];
}
});
});
}
//# sourceMappingURL=process-page.js.map