Skip to main content

Extend the import pipeline

Abstract

Example of how to modify the import pipeline behavior using a custom processor

You can extend the import pipeline for the code-first workflow to customize various aspects of your application's data.

This procedure shows you how to extend the import process to allow customizing the path of templates you create.

To extend the import pipeline:

  1. Extend your manifest data by adding your component to the JSS Manifest.

    export default manifest => {
      manifest.addComponent({
        name: "Welcome",
        // we added this property to our welcome component
        path: "/sitecore/templates/Welcome",
        fields: [
          { name: "title", type: manifest.fieldTypes.singleLineText },
        ]
      });
    };
  2. To make the custom path work, you must extend the import pipeline to alter how templates are created by the import process. Specifically, you must target the ProcessTemplates processor in the import pipeline, derive from it, and alter its behavior. For example:

    using System;
    using Sitecore.Data.Items;
    using Sitecore.Diagnostics;
    using Sitecore.JavaScriptServices.AppServices.Data;
    using Sitecore.JavaScriptServices.AppServices.Extensions;
    using Sitecore.JavaScriptServices.AppServices.Models;
    using Sitecore.JavaScriptServices.Configuration;
    
    namespace Sitecore.JavaScriptServices.AppServices.Pipelines.Import
    {
        public class ProcessTemplatesWithPath : ProcessTemplates
        {
            protected override TemplateItem CreateTemplate(TemplateDef templateDef, Item parent, Item multilistRoot, AppConfiguration app, IdManager idManager)
            {
                // the AdditionalData property is a dictionary of any JSON properties that were _not_ mapped to a TemplateDef property
                // so our path property - and any other custom properties that are added - will show up here. It will be null if no unmapped
                // properties exist so make sure to check everything for nulls with ?
                //
                // All import pipeline model objects have an AdditionalData property like this.
                var path = templateDef.AdditionalData?["path"]?.ToString();
    
                // path not set, use default behavior
                if (path == null) return base.CreateTemplate(templateDef, parent, multilistRoot, app, idManager);
    
                // resolve the custom path's parent (to keep things simple, we're not creating any parent hierarchy)
                var parentItemPath = path.Substring(0, path.LastIndexOf("/"));
                var customParentItem = parent.Database.GetItem(parentItemPath, parent.Language);
    
                if (customParentItem == null) throw new InvalidOperationException($"Parent item for custom import path item {templateDef.Name} ({path}) did not exist.");
    
                var templateName = ItemUtil.ProposeValidItemName(templateDef.Name);
    
                // JSS imports use _consistent IDs_ so that imports across instances use the same Sitecore item GUIDs
                // This code generates the consistent ID and ensures that it is unique.
                var templateId = idManager.GetTemplateId(app.Name, templateDef);
                idManager.AssertIdIsUnused(templateId, $"template {templateDef.Name}");
    
                // ensure we have permissions to create the item
                if (!customParentItem.CanImportChild(templateName, templateId, out var templateItem))
                {
                    return null;
                }
    
                if (templateItem == null)
                {
                    Log.Info($"[JSS] - Creating template - {templateName} (Custom path: {path})", this);
                    templateItem = parent.Database.Templates.CreateTemplate(templateName, customParentItem);
    
                    // make the db see our new template
                    parent.Database.Engines.TemplateEngine.Reset();
                }
                else
                {
                    Log.Debug($"[JSS] - Found existing template - {templateName}", this);
                }
    
                // sets the requisite fields on the template item
                UpdateTemplateItem(templateItem, templateDef, parent, multilistRoot, app, idManager, templateItem.DisplayName);
    
                return templateItem;
            }
        }
    }
  3. You must now tell Sitecore to use the custom processor ProcessTemplatesWithPath instead of the default ProcessTemplates processor. Create a configuration patch, for example App_Config/Include/PickAnyFileName.config and add the following configuration:

    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
      <sitecore role:require="ContentManagement or Standalone">
        <pipelines>
          <group groupName="javaScriptServices">
            <pipelines>
              <import>
                <processor 
                  type="Sitecore.JavaScriptServices.AppServices.Pipelines.Import.ProcessTemplatesWithPath, Sitecore.JavaScriptServices.AppServices"
                  patch:instead="*[contains(@type, 'ProcessTemplates')]" />
              </import>
            </pipelines>
          </group>
        </pipelines>
      </sitecore>
    </configuration>
  4. Deploy your JSS app:

    • If this is the first time deploying the app, in a terminal, run the following command:

      jss deploy app -c
    • Otherwise, run the following command:

      jss deploy items

    Note

    When you run one of the scripts, JSS generates the manifest automatically in the file sitecore/manifest/sitecore-import.json.

    The script outputs among other things, a message similar to the following:

    [JSS] - Creating template - Welcome (Custom path: /sitecore/templates/Welcome)
  5. In the Sitecore content tree, verify that the template was created at the path you requested.

    Note

    If you previously deployed your JSS app and have an existing template item in the default location, remove it and change any usage of it to the new template.