UNPKG

contentful-migration

Version:
208 lines 10.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const errors_1 = __importDefault(require("./errors")); const index_1 = require("./index"); const fieldErrors = errors_1.default.field; const deriveErrors = errors_1.default.entry.derivation; const transformErrors = errors_1.default.entry.transformation; const RELATIVE_MOVEMENTS = ['afterField', 'beforeField']; function fieldExists(validationContext, fieldId) { return validationContext.fieldSet.has(fieldId); } function fieldHasBeenRemoved(validationContext, fieldId) { return validationContext.fieldRemovals.has(fieldId); } function fieldHasBeenMoved(validationContext, movementKey) { return validationContext.fieldMovements.has(movementKey); } function idHasBeenChangedBefore(validationContext, oldId) { return Array.from(validationContext.fieldIdChanges.values()).includes(oldId); } const checks = { 'field/create': (errors, intent, validationContext) => { const id = intent.getFieldId(); const exists = fieldExists(validationContext, id); if (!exists) { validationContext.fieldSet.add(id); validationContext.fieldRemovals.delete(id); } if (exists) { errors.push((0, index_1.invalidActionError)(fieldErrors.create.FIELD_ALREADY_CREATED(id), intent)); } if (validationContext.fieldIdChanges.has(id)) { // a new field is created with the old id, so it's ok to use again validationContext.fieldIdChanges.delete(id); } }, 'field/update': (errors, intent, validationContext) => { const id = intent.getFieldId(); const exists = fieldExists(validationContext, id); const removed = fieldHasBeenRemoved(validationContext, id); const changedId = validationContext.fieldIdChanges.get(id); if (!exists && removed) { errors.push((0, index_1.invalidActionError)(fieldErrors.update.FIELD_ALREADY_DELETED(id), intent)); } if (changedId) { errors.push((0, index_1.invalidActionError)(fieldErrors.changeId.REFERENCE_TO_OLD_ID(id, changedId), intent)); } else if (!exists && !removed) { errors.push((0, index_1.invalidActionError)(fieldErrors.update.FIELD_DOES_NOT_EXIST(id), intent)); } }, 'field/delete': (errors, intent, validationContext) => { const id = intent.getFieldId(); const exists = fieldExists(validationContext, id); const removed = fieldHasBeenRemoved(validationContext, id); if (exists) { validationContext.fieldSet.delete(id); validationContext.fieldRemovals.add(id); } if (!exists && removed) { errors.push((0, index_1.invalidActionError)(fieldErrors.delete.FIELD_ALREADY_DELETED(id), intent)); } if (!exists && !removed) { errors.push((0, index_1.invalidActionError)(fieldErrors.delete.FIELD_DOES_NOT_EXIST(id), intent)); } }, 'field/move': (errors, intent, validationContext) => { const id = intent.getFieldId(); const pivot = intent.getPivotId(); const exists = fieldExists(validationContext, id); const removed = fieldHasBeenRemoved(validationContext, id); const moved = fieldHasBeenMoved(validationContext, intent.getFieldMovementKey()); const isRelativeMovement = RELATIVE_MOVEMENTS.includes(intent.getDirection()); validationContext.fieldMovements.add(intent.getFieldMovementKey()); if (isRelativeMovement) { const pivotExists = fieldExists(validationContext, pivot); const pivotRemoved = fieldHasBeenRemoved(validationContext, pivot); const direction = intent.getDirection() === 'afterField' ? 'after' : 'before'; if (!pivotExists && !pivotRemoved) { errors.push((0, index_1.invalidActionError)(fieldErrors.move.PIVOT_FIELD_DOES_NOT_EXIST(intent.getPivotId(), direction), intent)); } if (!pivotExists && pivotRemoved) { errors.push((0, index_1.invalidActionError)(fieldErrors.move.PIVOT_FIELD_DELETED(intent.getPivotId(), direction), intent)); } } if (!exists && removed) { errors.push((0, index_1.invalidActionError)(fieldErrors.move.FIELD_DELETED(id), intent)); } if (!exists && !removed) { errors.push((0, index_1.invalidActionError)(fieldErrors.move.FIELD_DOES_NOT_EXIST(id), intent)); } if (moved) { errors.push((0, index_1.invalidActionError)(fieldErrors.move.FIELD_ALREADY_MOVED(id), intent)); } }, 'field/rename': (errors, intent, validationContext) => { checks['field/update'](errors, intent, validationContext); const oldId = intent.getFieldId(); const newId = intent.getNewId(); if (idHasBeenChangedBefore(validationContext, oldId)) { errors.push((0, index_1.invalidActionError)(fieldErrors.changeId.NO_MULTIPLE_ID_CHANGES(oldId), intent)); } if (oldId === newId) { errors.push((0, index_1.invalidActionError)(fieldErrors.changeId.ID_MUST_BE_DIFFERENT(oldId), intent)); } else if (fieldExists(validationContext, newId)) { errors.push((0, index_1.invalidActionError)(fieldErrors.changeId.ID_ALREADY_EXISTS(oldId, newId, intent.getContentTypeId()), intent)); } // remember this field's old id, so that we can check if it is erroneously used later on validationContext.fieldIdChanges.set(oldId, newId); validationContext.fieldSet.delete(oldId); validationContext.fieldSet.add(newId); }, 'contentType/transformEntries': (errors, intent, validationContext) => { const wrapError = (message, intent) => { return { type: 'InvalidEntriesTransformation', message, details: { intent } }; }; const transformation = intent.toRaw().payload.transformation; const nonExistingSourceFields = transformation.from.filter((f) => !validationContext.fieldSet.has(f)); const nonExistingDestinationFields = transformation.to.filter((f) => !validationContext.fieldSet.has(f)); const nonExistingFields = nonExistingSourceFields.concat(nonExistingDestinationFields); if (nonExistingFields.length > 0) { errors.push(wrapError(transformErrors.NON_EXISTING_FIELDS(intent.getContentTypeId(), nonExistingFields), intent)); } } }; function default_1(intents, contentTypes = []) { const errors = []; const contentTypeFields = contentTypes.reduce((acc, curr) => { const fieldIds = curr.fields.map((f) => f.id); acc[curr.id] = new Set(fieldIds); return acc; }, {}); const recentlyRemoved = {}; const recentlyMoved = {}; const changedFieldIds = {}; for (const intent of intents) { const contentTypeId = intent.getContentTypeId(); const contentTypeExists = Boolean(contentTypes.find((ct) => ct.id === contentTypeId)); const fieldSet = contentTypeFields[contentTypeId] || new Set(); const fieldRemovals = recentlyRemoved[contentTypeId] || new Set(); const fieldMovements = recentlyMoved[contentTypeId] || new Set(); const fieldIdChanges = changedFieldIds[contentTypeId] || new Map(); const validationContext = { fieldSet, fieldRemovals, fieldMovements, fieldIdChanges }; if (intent.isAboutField()) { const fieldId = intent.getFieldId(); if (!contentTypeExists) { const type = intent.getRawType().split('/')[1]; errors.push((0, index_1.invalidActionError)(fieldErrors[type].CONTENT_TYPE_DOES_NOT_EXIST(fieldId, contentTypeId), intent)); continue; } checks[intent.getRawType()](errors, intent, validationContext); } if (intent.isContentTransform()) { checks[intent.getRawType()](errors, intent, validationContext); } // We need to keep track of field creations and removals // So this is the only place we can do this without duplication if (intent.isEntryDerive()) { const wrapError = (message, intent) => { return { type: 'InvalidEntriesDerivation', message, details: { intent } }; }; const derivation = intent.toRaw().payload.derivation; const sourceCT = contentTypes.find((ct) => ct.id === intent.getContentTypeId()); const destinationCT = contentTypes.find((ct) => ct.id === derivation.derivedContentType); const destinationFields = contentTypeFields[destinationCT.id]; const nonExistingSourceFields = derivation.from.filter((f) => !fieldSet.has(f)); const nonExistingToReferenceField = !fieldSet.has(derivation.toReferenceField); const nonExistingDestinationFields = destinationFields ? derivation.derivedFields.filter((f) => !destinationFields.has(f)) : derivation.derivedFields; if (nonExistingSourceFields.length > 0) { errors.push(wrapError(deriveErrors.NON_EXISTING_SOURCE_FIELDS(sourceCT.id, nonExistingSourceFields), intent)); } if (nonExistingToReferenceField) { errors.push(wrapError(deriveErrors.NON_EXISTING_REFERENCE_FIELD(sourceCT.id, derivation.toReferenceField), intent)); } if (nonExistingDestinationFields.length > 0) { errors.push(wrapError(deriveErrors.NON_EXISTING_DESTINATION_FIELDS(destinationCT.id, nonExistingDestinationFields), intent)); } } contentTypeFields[contentTypeId] = fieldSet; recentlyRemoved[contentTypeId] = fieldRemovals; recentlyMoved[contentTypeId] = fieldMovements; changedFieldIds[contentTypeId] = fieldIdChanges; } return { errors, fieldsContext: { contentTypeFields, recentlyRemoved, recentlyMoved, changedFieldIds } }; } exports.default = default_1; //# sourceMappingURL=field.js.map