Search code examples
contentfulcontentful-api

Contentful migrations: How to migrate a link to an asset?


I have a content type 'blogpost' that currently contains a reference to another content type called 'image'. The content type 'image' has a link to an asset, an image file.

Now I want to create a migration script where I link directly from the 'blogpost' entry to the asset.

Current content model:
entry 'My blog post'
  → field 'image' 
    → link to entry 'My image entry' 
      → field 'image' 
        → link to asset 'My image asset'

Transform to:
entry 'My blog post' 
  → field 'mainImage' 
    → link to asset 'My image asset'

This is the migration so far:

module.exports = function (migration, { makeRequest }) {

    // Create new mainImage field in blogpost content type
    const blogpost = migration.editContentType('blogpost');
    blogpost
        .createField('mainImage')
        .name('Main Image')
        .type('Link')
        .linkType('Asset')
        .validations([
            {
                'linkMimetypeGroup': ['image']
            }
        ]);

    migration.transformEntries({
        contentType: 'blogpost',
        from: ['image'],
        to: ['mainImage'],
        transformEntryForLocale: async function (fromFields, currentLocale) {

            // Get the the entry of type 'image' from the blogpost's 'image' field
            const imageEntryId = fromFields.image[currentLocale].sys.id;
            const imageEntry = await makeRequest({
                method: 'GET',
                url: `/entries/${imageEntryId}`
            });

            return { mainImage: imageEntry.fields.image[currentLocale] };
        }
    });
}

I have tried mapping the 'mainImage' field to different parts of imageEntry.fields.image and imageAsset but I cannot seem to get the mapping right.

I usually get this error message when I run the migration script. My locale is 'nb-NO':

TypeError: Cannot read properties of undefined (reading 'nb-NO')


Solution

  • I finally figured out what I did wrong and what the error message above meant.

    The migration script itself worked as expected, but it crashed for the blogpost entries that didn’t have an image.

    This line crashed when fromFields.image was null:

    const imageEntryId = fromFields.image[currentLocale].sys.id;
    

    I replaced it with the following null check:

    if (fromFields.image === null || typeof (fromFields.image) === "undefined") {
        return;
    }
        
    const imageEntryId = fromFields.image[currentLocale].sys.id;