Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
113 lines (83 sloc) 4.92 KB
---
title: How To: Extend the Product Schema
---

Prerequisite Reading

Overview

As a developer customizing Reaction, you may find a need to add some custom property to products. You should avoid this if you can achieve your goals some other way, such as using metafields, tags, or a separate data store that references product IDs. But in some cases, extending products is the best way.

Because products have a publishing flow and have variants, extending them requires many steps. In general, they are as follows:

  • Extend database schemas
  • Extend GraphQL schemas
  • Register your custom property as published, if it should be published to the catalog
  • Register a function that publishes your custom property, if it should be published to the catalog
  • Create a GraphQL mutation for setting your custom property value
  • Create a React component that allows an operator to set the custom property value, and wire it up to your mutation, or set your property in some other way

Extend database schemas

To extend any database schema, you just need a file that is imported into server code. We recommend using a file named dbschema.js in your plugin's server/no-meteor folder, and then importing that file in your plugin's server/index.js. (The no-meteor folder helps keep track of which files rely on Meteor while Reaction is transitioning from Meteor to pure Node. If your plugin has no Meteor dependencies, you may omit that folder level.)

Refer to SimpleSchema docs for more information about the object you pass to extend.

import {
  CatalogProduct,
  CatalogVariantSchema,
  Product,
  ProductVariant,
  VariantBaseSchema
} from "/imports/collections/schemas";

const schemaExtension = {
  myProperty: {
    type: String,
    optional: true
  }
};

// Extend the Product database schema, if your custom property will be on products
Product.extend(schemaExtension);

// Extend the Variant database schema, if your custom property will be on variants
ProductVariant.extend(schemaExtension);

// Extend the CatalogProduct database schema, if your custom property will be on products
CatalogProduct.extend(schemaExtension);

// Extend the catalog variant database schemas, if your custom property will be on variants. There are two schemas for this one.
VariantBaseSchema.extend(schemaExtension);
CatalogVariantSchema.extend(schemaExtension);

Extend GraphQL schemas

  • Extend the Product GraphQL type, if your custom property will be on products
  • Extend the ProductVariant GraphQL type, if your custom property will be on variants
  • Extend the CatalogProduct GraphQL type, if your custom property will be on products and is published to the catalog
  • Extend the CatalogProductVariant GraphQL type, if your custom property will be on variants and is published to the catalog
  • Create a GraphQL resolver for your property if it needs any transformation

Refer to How To: Extend GraphQL to add a field.

Register custom property as published

Skip this step if your property is not needed in the published catalog

A plugin can include a catalog object in registerPackage, with customPublishedProductFields and customPublishedProductVariantFields that are set to arrays of property names. These will be appended to the core list of fields for which published status should be tracked. This is used to build the hashes that are used to display an indicator when changes need to be published.

import Reaction from "/imports/plugins/core/core/server/Reaction";

Reaction.registerPackage({
  catalog: {
    customPublishedProductFields: ["myProperty"],
    customPublishedProductVariantFields: ["myProperty"]
  },
  // ...other props
});

Register a function that publishes custom property

Skip this step if your property is not needed in the published catalog

import Reaction from "/imports/plugins/core/core/server/Reaction";
import publishProductToCatalog from "./server/no-meteor/publishProductToCatalog";

Reaction.registerPackage({
  functionsByType: {
    publishProductToCatalog: [publishProductToCatalog]
  },
  // ...other props
});

Where the publishProductToCatalog function looks something like this:

export default function publishProductToCatalog(catalogProduct, { context, product, shop, variants }) {
  catalogProduct.myProperty = product.myProperty;
  // Also set on each catalogProduct.variants if necessary
}

Create a GraphQL mutation for setting your custom property value

Refer to How To: Create a new GraphQL mutation. After mutating the Product document in your function, you must also call context.mutations.hashProduct(productId, context.collections, false). This will update the current product hash, causing the operator UI to indicate that there are changes needing publishing.

You can’t perform that action at this time.