contentful-migration
Version:
Migration tooling for contentful
608 lines • 22.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EditorInterfaces = exports.Fields = exports.ContentType = exports.default = void 0;
const lodash_1 = require("lodash");
const sidebarwidget_1 = require("../action/sidebarwidget");
const editor_layout_1 = require("../utils/editor-layout");
function prune(obj) {
if (obj === undefined) {
return undefined;
}
if (Array.isArray(obj)) {
return obj.length === 0 ? undefined : obj;
}
let isEmpty = true;
for (const [key, value] of Object.entries(obj)) {
if (!prune(value)) {
delete obj[key];
}
else {
isEmpty = false;
}
}
return isEmpty ? undefined : obj;
}
class Fields {
constructor(contentType, fields = []) {
this._contentType = contentType;
this._fields = fields;
}
getField(id) {
return (0, lodash_1.find)(this._fields, { id });
}
setField(id, field) {
const allFields = this.fields;
const currentFieldIndex = allFields.findIndex((field) => field.id === id);
if (currentFieldIndex === -1) {
allFields.push(field);
}
else {
allFields[currentFieldIndex] = field;
}
if (field.deleted) {
this._contentType.clearFieldAnnotations(id);
}
this._fields = allFields;
}
deleteField(id) {
const fieldToDelete = (0, lodash_1.find)(this._fields, { id });
(0, lodash_1.pull)(this._fields, fieldToDelete);
this._contentType.clearFieldAnnotations(id);
}
moveField(id, direction, pivot) {
const fields = this._fields;
const field = this.getField(id);
(0, lodash_1.pull)(fields, field);
if (direction === 'toTheTop') {
fields.unshift(field);
}
if (direction === 'toTheBottom') {
fields.push(field);
}
const pivotIndex = (0, lodash_1.findIndex)(fields, { id: pivot });
if (direction === 'afterField') {
fields.splice(pivotIndex + 1, 0, field);
}
if (direction === 'beforeField') {
fields.splice(pivotIndex, 0, field);
}
}
filter(predicate) {
return (0, lodash_1.filter)(this._fields, predicate);
}
map(mapper) {
return this._fields.map(mapper);
}
get fields() {
return this._fields;
}
set fields(fields) {
this._fields = fields;
}
clone() {
return new Fields(this._contentType.clone(), this.toRaw());
}
toRaw() {
return (0, lodash_1.cloneDeep)(this.fields);
}
}
exports.Fields = Fields;
class EditorInterfaces {
constructor(apiEditorInterfaces) {
this._version = apiEditorInterfaces.sys.version;
this._controls = apiEditorInterfaces.controls;
this._sidebar = apiEditorInterfaces.sidebar || undefined;
this._editor = apiEditorInterfaces.editor || undefined;
this._editors = apiEditorInterfaces.editors || undefined;
this._editorLayout = apiEditorInterfaces.editorLayout || undefined;
this._groupControls = apiEditorInterfaces.groupControls || undefined;
}
get version() {
return this._version;
}
set version(version) {
this._version = version;
}
getSidebar() {
return this._sidebar;
}
getEditor() {
return this._editor;
}
getEditors() {
return this._editors;
}
getControls() {
return this._controls;
}
getEditorLayout() {
return this._editorLayout;
}
getGroupControls() {
return this._groupControls;
}
reset(fieldId) {
let controlIndex = (0, lodash_1.findIndex)(this._controls, (c) => {
return c.fieldId === fieldId;
});
if (controlIndex !== -1) {
this._controls.splice(controlIndex, 1);
}
}
copy(fromFieldId, toFieldId) {
let control = (0, lodash_1.find)(this._controls, (c) => {
return c.fieldId === fromFieldId;
});
if (control) {
this.update(toFieldId, control.widgetId, control.settings, control.widgetNamespace);
}
}
update(fieldId, widgetId, settings, widgetNamespace) {
let control = (0, lodash_1.find)(this._controls, (c) => {
return c.fieldId === fieldId;
});
if (!control) {
control = {
fieldId: fieldId,
widgetId: widgetId
};
control.fieldId = fieldId;
this._controls.push(control);
}
control.widgetId = widgetId;
if (settings) {
(0, lodash_1.forEach)(settings, (v, k) => {
control.settings = control.settings || {};
control.settings[k] = v;
});
}
if (widgetNamespace) {
control.widgetNamespace = widgetNamespace;
}
}
addSidebarWidget(widgetId, widgetNamespace, settings, insertBeforeWidgetId, disabled) {
this._sidebar = Array.isArray(this._sidebar) ? this._sidebar : [].concat(sidebarwidget_1.DEFAULT_SIDEBAR_LIST);
const isDuplicateWidget = this._sidebar.find((widget) => widget.widgetId === widgetId && widget.widgetNamespace === widgetNamespace);
if (isDuplicateWidget) {
return;
}
const nextWidgetIndex = this._sidebar.map((w) => w.widgetId).indexOf(insertBeforeWidgetId);
const newWidget = {
disabled,
settings,
widgetId,
widgetNamespace
};
if (nextWidgetIndex < 0) {
this._sidebar.push(newWidget);
}
else {
this._sidebar.splice(nextWidgetIndex, 0, newWidget);
}
}
updateSidebarWidget(widgetId, widgetNamespace, settings, disabled) {
this._sidebar = Array.isArray(this._sidebar) ? this._sidebar : [].concat(sidebarwidget_1.DEFAULT_SIDEBAR_LIST);
const existingWidget = this._sidebar.find((widget) => widget.widgetId === widgetId && widget.widgetNamespace === widgetNamespace);
if (!existingWidget) {
return;
}
existingWidget.settings = settings ? settings : existingWidget.settings;
existingWidget.disabled = typeof disabled === 'boolean' ? disabled : existingWidget.disabled;
}
removeSidebarWidget(widgetId, widgetNamespace) {
const currentSidebarWidgets = Array.isArray(this._sidebar)
? this._sidebar
: [].concat(sidebarwidget_1.DEFAULT_SIDEBAR_LIST);
const widgetToDisable = currentSidebarWidgets.find((widget) => widget.widgetId === widgetId && widget.widgetNamespace === widgetNamespace);
if (!widgetToDisable) {
return;
}
this._sidebar = currentSidebarWidgets.filter((widget) => widget.widgetId !== widgetId || widget.widgetNamespace !== widgetNamespace);
}
resetSidebarToDefault() {
this._sidebar = undefined;
}
resetEditorToDefault() {
this._editor = undefined;
this._editors = undefined;
}
setEditor(editor) {
this._editor = editor;
}
setEditors(editors) {
this._editors = editors;
}
createEditorLayout(fields) {
// A newly created editor layout doesn’t have the correct shape. This is corrected when adding the first group.
this._editorLayout = fields.map((field) => ({
fieldId: field.id
}));
}
deleteEditorLayout() {
delete this._groupControls;
delete this._editorLayout;
}
createEditorLayoutFieldGroup(fieldGroupId, parentFieldGroupId) {
if (parentFieldGroupId) {
// create field set
const parent = (0, editor_layout_1.findFieldGroup)(this._editorLayout, parentFieldGroupId);
parent.item.items.push({
groupId: fieldGroupId,
items: []
});
}
else {
// create tab
const hasFieldGroup = this._editorLayout.some((item) => (0, editor_layout_1.isFieldGroupItem)(item));
if (hasFieldGroup) {
this._editorLayout.push({
groupId: fieldGroupId,
items: []
});
}
else {
this._editorLayout = [
{
groupId: fieldGroupId,
items: [...this._editorLayout]
}
];
}
}
}
createFieldInEditorLayout(fieldId) {
var _a;
if (((_a = this._editorLayout) === null || _a === void 0 ? void 0 : _a.length) > 0) {
let fieldItem = (0, editor_layout_1.find)(this._editorLayout, (editorLayoutItem) => isTargetFieldItem(editorLayoutItem, fieldId));
if (!fieldItem) {
this._editorLayout[0].items.push({ fieldId });
}
}
}
deleteEditorLayoutFieldGroup(fieldGroupId) {
const fieldGroup = (0, editor_layout_1.findFieldGroup)(this._editorLayout, fieldGroupId);
if (!fieldGroup) {
return;
}
const parentPath = fieldGroup.path.slice(0, -1);
const groupIndex = fieldGroup.path[fieldGroup.path.length - 1];
if (parentPath.length === 0) {
this._editorLayout = this._editorLayout.filter((item) => item.groupId !== fieldGroupId);
this._editorLayout[0].items = [...this._editorLayout[0].items, ...fieldGroup.item.items];
return;
}
(0, lodash_1.update)(this._editorLayout, parentPath, (prev) => {
const group = prev[groupIndex];
return [...prev.slice(0, groupIndex), ...group.items, ...prev.slice(groupIndex + 1)];
});
}
deleteFieldFromEditorLayout(fieldId) {
var _a;
if (((_a = this._editorLayout) === null || _a === void 0 ? void 0 : _a.length) > 0) {
// find the field and its parent (sourceGroup) within editorLayout
let fieldItem;
const { item: parentItem } = (0, editor_layout_1.find)(this._editorLayout, (item) => (0, editor_layout_1.isFieldGroupItem)(item) &&
Boolean(item.items.find((item) => {
if (isTargetFieldItem(item, fieldId)) {
fieldItem = item;
return true;
}
return false;
})));
// remove field item from original group
if (parentItem) {
(0, lodash_1.pull)(parentItem.items, fieldItem);
}
}
}
changeFieldGroupId(fieldGroupId, newFieldGroupId) {
const fieldGroup = (0, editor_layout_1.findFieldGroup)(this._editorLayout, fieldGroupId);
if (fieldGroup === null || fieldGroup === void 0 ? void 0 : fieldGroup.item) {
fieldGroup.item.groupId = newFieldGroupId;
}
const existingGroupControl = this._groupControls.find((control) => control.groupId === fieldGroupId);
if (existingGroupControl) {
existingGroupControl.groupId = newFieldGroupId;
}
}
updateEditorLayoutFieldGroup(fieldGroupId, props) {
const fieldGroup = (0, editor_layout_1.findFieldGroup)(this._editorLayout, fieldGroupId);
Object.assign(fieldGroup.item, (0, lodash_1.pick)(props, ['name']));
}
createGroupControls() {
this._groupControls = [];
}
createTabGroupControl(fieldGroupId) {
this._groupControls.push({
groupId: fieldGroupId,
widgetId: 'topLevelTab',
widgetNamespace: 'builtin'
});
}
updateGroupControl(fieldGroupId, groupControl) {
var _a;
const existingGroupControl = this._groupControls.find((control) => control.groupId === fieldGroupId);
if (existingGroupControl) {
existingGroupControl.widgetId = groupControl.widgetId;
existingGroupControl.widgetNamespace = groupControl.widgetNamespace;
if (groupControl.settings !== undefined) {
existingGroupControl.settings = groupControl.settings;
}
}
else {
this._groupControls.push({
groupId: fieldGroupId,
widgetId: groupControl.widgetId,
widgetNamespace: groupControl.widgetNamespace,
settings: (_a = groupControl.settings) !== null && _a !== void 0 ? _a : {}
});
}
}
updateFieldIdInEditorLayout(oldFieldId, newFieldId) {
var _a;
if (((_a = this._editorLayout) === null || _a === void 0 ? void 0 : _a.length) > 0) {
let { item: fieldItem } = (0, editor_layout_1.find)(this._editorLayout, (editorLayoutItem) => isTargetFieldItem(editorLayoutItem, oldFieldId));
if (!!fieldItem) {
fieldItem.fieldId = newFieldId;
}
}
}
deleteGroupControl(fieldGroupId) {
this._groupControls = this._groupControls.filter((control) => control.groupId !== fieldGroupId);
}
moveFieldInEditorLayout(fieldId, direction, pivot) {
// find the field and its parent (sourceGroup) within editorLayout
let fieldItem;
const { item: sourceGroupItem } = (0, editor_layout_1.find)(this._editorLayout, (item) => (0, editor_layout_1.isFieldGroupItem)(item) &&
Boolean(item.items.find((item) => {
if (isTargetFieldItem(item, fieldId)) {
fieldItem = item;
return true;
}
return false;
})));
// remove field item from original group
if (sourceGroupItem) {
(0, lodash_1.pull)(sourceGroupItem.items, fieldItem);
}
else {
fieldItem = { fieldId };
}
// here it's assumed the field is moved within its group. If not the case, later below destination is updated
let destinationGroupItem = sourceGroupItem;
const findGroupItem = (groupId) => {
const { item } = (0, editor_layout_1.find)(this._editorLayout, (item) => isTargetGroupItem(item, groupId));
return item;
};
let pivotIndex;
if (direction === 'toTheTopOfFieldGroup') {
if (pivot) {
destinationGroupItem = findGroupItem(pivot);
}
pivotIndex = 0;
}
else if (direction === 'toTheBottomOfFieldGroup') {
if (pivot) {
destinationGroupItem = findGroupItem(pivot);
}
pivotIndex = destinationGroupItem.items.length;
}
else {
const movementConfigMap = {
afterField: {
isTargetPivot: (item) => isTargetFieldItem(item, pivot),
pivotIndexOffset: 1
},
beforeField: {
isTargetPivot: (item) => isTargetFieldItem(item, pivot),
pivotIndexOffset: 0
},
afterFieldGroup: {
isTargetPivot: (item) => isTargetGroupItem(item, pivot),
pivotIndexOffset: 1
},
beforeFieldGroup: {
isTargetPivot: (item) => isTargetGroupItem(item, pivot),
pivotIndexOffset: 0
}
};
const movementConfig = movementConfigMap[direction];
// find the parent group of target pivot
const { item: pivotParent } = (0, editor_layout_1.find)(this._editorLayout, (item) => (0, editor_layout_1.isFieldGroupItem)(item) &&
Boolean(item.items.find((childItem, childItemIndex) => {
if (movementConfig.isTargetPivot(childItem)) {
pivotIndex = childItemIndex + movementConfig.pivotIndexOffset;
return true;
}
return false;
})));
destinationGroupItem = pivotParent;
}
destinationGroupItem.items.splice(pivotIndex, 0, fieldItem);
}
toAPI() {
let controls = [];
(0, lodash_1.forEach)(this._controls, (c) => {
controls.push({
fieldId: c.fieldId,
widgetId: c.widgetId,
settings: c.settings,
widgetNamespace: c.widgetNamespace
});
});
const result = {
controls
};
if (this._sidebar) {
result.sidebar = this._sidebar;
}
// prefer editors over editor
if (this._editors) {
result.editors = this._editors;
}
else if (this._editor) {
result.editor = this._editor;
}
if (this._editorLayout) {
result.editorLayout = this._editorLayout;
}
if (this._groupControls) {
result.groupControls = this._groupControls;
}
return (0, lodash_1.cloneDeep)(result);
}
}
exports.EditorInterfaces = EditorInterfaces;
class ContentType {
constructor(ct) {
this._id = ct.sys.id;
this._fields = new Fields(this, ct.fields);
this._name = ct.name;
this._description = ct.description;
this._version = ct.sys.version;
this._displayField = ct.displayField;
this._metadata = ct.metadata;
}
get id() {
return this._id;
}
get fields() {
return this._fields;
}
set fields(fields) {
this._fields = fields;
}
get name() {
return this._name;
}
set name(name) {
this._name = name;
}
get description() {
return this._description;
}
set description(description) {
this._description = description;
}
get displayField() {
return this._displayField;
}
set displayField(displayField) {
this._displayField = displayField;
}
setAnnotations(annotations) {
(0, lodash_1.set)(this, '_metadata.annotations.ContentType', annotations);
}
getAnnotations() {
var _a, _b;
return (_b = (_a = this._metadata) === null || _a === void 0 ? void 0 : _a.annotations) === null || _b === void 0 ? void 0 : _b.ContentType;
}
clearAnnotations() {
var _a, _b;
(_b = (_a = this._metadata) === null || _a === void 0 ? void 0 : _a.annotations) === null || _b === void 0 ? true : delete _b.ContentType;
}
setFieldAnnotations(fieldId, annotations, fieldAnnotationPayload) {
(0, lodash_1.set)(this, `_metadata.annotations.ContentTypeField.${fieldId}`, Object.assign(annotations, fieldAnnotationPayload));
}
getFieldAnnotations(fieldId) {
var _a, _b, _c;
return (_c = (_b = (_a = this._metadata) === null || _a === void 0 ? void 0 : _a.annotations) === null || _b === void 0 ? void 0 : _b.ContentTypeField) === null || _c === void 0 ? void 0 : _c[fieldId];
}
clearFieldAnnotations(fieldId) {
var _a, _b, _c;
(_c = (_b = (_a = this._metadata) === null || _a === void 0 ? void 0 : _a.annotations) === null || _b === void 0 ? void 0 : _b.ContentTypeField) === null || _c === void 0 ? true : delete _c[fieldId];
}
setTaxonomyValidations(taxonomyValidations) {
(0, lodash_1.set)(this, '_metadata.taxonomy', taxonomyValidations);
}
addTaxonomyValidation(id, linkType, options = {}) {
const current = this.getTaxonomyValidation() || [];
// Check if validation already exists for this ID
const existingIndex = current.findIndex((validation) => validation.sys.id === id);
let newValidation;
if (linkType === 'TaxonomyConcept') {
newValidation = {
sys: {
type: 'Link',
linkType: 'TaxonomyConcept',
id
}
};
}
else {
newValidation = {
sys: {
type: 'Link',
linkType: 'TaxonomyConceptScheme',
id
}
};
}
if (options.required !== undefined) {
newValidation.required = options.required;
}
if (existingIndex >= 0) {
// Update existing validation
current[existingIndex] = newValidation;
}
else {
// Add new validation
current.push(newValidation);
}
this.setTaxonomyValidations(current);
}
clearTaxonomyValidations() {
// Ensure metadata object exists before setting taxonomy
if (!this._metadata) {
this._metadata = {};
}
this._metadata.taxonomy = [];
}
getTaxonomyValidation() {
var _a;
return (_a = this._metadata) === null || _a === void 0 ? void 0 : _a.taxonomy;
}
get version() {
return this._version;
}
set version(version) {
this._version = version;
}
toAPI() {
const basePayload = {
sys: {
id: this.id,
version: this.version
},
name: this.name,
displayField: this.displayField,
fields: this.fields.toRaw(),
description: this.description
};
if (this._metadata) {
const metadata = {};
// Simple rule: preserve all arrays in metadata (empty or not)
if (this._metadata.taxonomy !== undefined) {
metadata.taxonomy = this._metadata.taxonomy;
}
if (this._metadata.annotations) {
const prunedAnnotations = prune(this._metadata.annotations);
if (prunedAnnotations) {
metadata.annotations = prunedAnnotations;
}
}
if (Object.keys(metadata).length > 0) {
basePayload.metadata = metadata;
}
}
return (0, lodash_1.cloneDeep)(basePayload);
}
clone() {
return new ContentType(this.toAPI());
}
}
exports.default = ContentType;
exports.ContentType = ContentType;
const isTargetFieldItem = (item, fieldId) => (0, editor_layout_1.isFieldItem)(item) && item.fieldId === fieldId;
const isTargetGroupItem = (item, groupId) => (0, editor_layout_1.isFieldGroupItem)(item) && item.groupId === groupId;
//# sourceMappingURL=content-type.js.map