"The list of currently supported social network identifiers"
enum SocialNetwork {
  "Facebook"
  facebook

  "Google+"
  googleplus

  "Pinterest"
  pinterest

  "Twitter"
  twitter
}

"The list of currently supported top level Catalog props on which catalog items can be filtered."
enum CatalogBooleanFilterName {
  "isDeleted"
  isDeleted

  "isVisible"
  isVisible
}

"A filter to be applied to a Catalog query"
input CatalogBooleanFilter {
  "The name of the filter"
  name: CatalogBooleanFilterName!

  "The filter value"
  value: Boolean!
}

"Holds metadata specific to a specific social network service"
type SocialMetadata {
  "Default share message to use when sharing this product on this social network"
  message: String

  "Which social network is this metadata for"
  service: SocialNetwork
}

"This interface represents the fields that are identical for both Products and Variants"
interface CatalogProductOrVariant {
  "The product barcode value, if it has one"
  barcode: String

  # This should be required but we need to migrate existing data first
  "The date and time at which this CatalogProduct was created, which is when the related product was first published"
  createdAt: DateTime

  "The height of the product, if it has physical dimensions"
  height: Float

  "The length of the product, if it has physical dimensions"
  length: Float

  "Arbitrary additional metadata about this product"
  metafields: [Metafield]

  "The minimum quantity that must be added to a cart"
  minOrderQuantity: Int

  "The country of origin"
  originCountry: String

  "The shop to which this product belongs"
  shop: Shop!

  "A stock keeping unit (SKU) identifier for this product"
  sku: String

  "Product or variant title"
  title: String

  # This should be required but we need to migrate existing data first
  "The date and time at which this CatalogProduct was last updated, which is when the related product was most recently published"
  updatedAt: DateTime

  "The weight of the product on Earth, if it has physical dimensions"
  weight: Float

  "The width of the product, if it has physical dimensions"
  width: Float
}

"""
Represents a product that has been published into a shop catalog. The related `Product` is the source of truth for
shop administrators, but that is then published to a catalog as a `CatalogProduct`, which is what should
be displayed to shoppers who browse that catalog.
"""
type CatalogProduct implements CatalogProductOrVariant & Node {
  "The CatalogProduct ID. Do not assume that this is the same as the related product ID. See `productId` for that."
  _id: ID!

  "The product barcode value, if it has one"
  barcode: String

  "The date and time at which this CatalogProduct was created, which is when the related product was first published"
  createdAt: DateTime!

  "The full product description, which may have newline characters in it"
  description: String

  "The height of the product, if it has physical dimensions"
  height: Float

  "True if this product has been deleted. Typically, deleted products are not returned in queries."
  isDeleted: Boolean!

  "True if this product should be shown to shoppers. Typically, non-visible products are not returned in queries."
  isVisible: Boolean!

  "The length of the product, if it has physical dimensions"
  length: Float

  "All media for this product and its variants"
  media: [ImageInfo]

  "The product description to use for page `description` meta element in HTML"
  metaDescription: String

  "Arbitrary additional metadata about this product"
  metafields: [Metafield]

  "The minimum quantity that must be added to a cart"
  minOrderQuantity: Int

  "The country of origin"
  originCountry: String

  "Subtitle"
  pageTitle: String

  "Dimensions and other information about the containers in which this product will be shipped"
  parcel: ShippingParcel

  "The primary image"
  primaryImage: ImageInfo

  "The related Product ID"
  productId: ID!

  "An arbitrary product type value, such as from an external system"
  productType: String

  "The shop to which this product belongs"
  shop: Shop!

  "A stock keeping unit (SKU) identifier for this product"
  sku: String

  "A URL-safe and human-readable string that uniquely identifies this product"
  slug: String

  "Holds metadata specific to a specific social network service"
  socialMetadata: [SocialMetadata]

  "When a shopper purchases this product, what types of fulfillment can they choose from?"
  supportedFulfillmentTypes: [FulfillmentType]!

  "Product title"
  title: String

  "The date and time at which this CatalogProduct was last updated, which is when the related product was most recently published"
  updatedAt: DateTime!

  "A flat list of all variants for this product"
  variants: [CatalogProductVariant]

  "The product vendor or manufacturer, for display"
  vendor: String

  "The weight of the product on Earth, if it has physical dimensions"
  weight: Float

  "The width of the product, if it has physical dimensions"
  width: Float
}

"A variant of a catalog product"
type CatalogProductVariant implements CatalogProductOrVariant & Node {
  "The CatalogProductVariant ID. Do not assume that this is the same as the related variant ID. See `variantId` for that."
  _id: ID!

  """
  The attribute label describes the category of variant, for example, `Color` or `Size`.
  In most cases this will be the same for all variants at the same level.
  """
  attributeLabel: String!

  "The product variant barcode value, if it has one"
  barcode: String

  "The date and time at which this CatalogProductVariant was created, which is when the related product was first published"
  createdAt: DateTime

  "The height of the product variant, if it has physical dimensions"
  height: Float

  "The position of this variant among other variants at the same level of the product-variant-option hierarchy"
  index: Int!

  "The length of the product, if it has physical dimensions"
  length: Float

  "All media for this variant / option"
  media: [ImageInfo]

  "Arbitrary additional metadata about this product"
  metafields: [Metafield]

  "The minimum quantity that must be added to a cart"
  minOrderQuantity: Int

  "A short title to use for product detail select lists"
  optionTitle: String

  "Child variants, if any"
  options: [CatalogProductVariant]

  "The country of origin"
  originCountry: String

  "The primary image of this variant / option"
  primaryImage: ImageInfo

  "The shop to which this product variant belongs"
  shop: Shop!

  "A stock keeping unit (SKU) identifier for this product"
  sku: String

  """
  The full variant title for use on cart, checkout, and order summaries and on invoices.
  This fully describes the configured variant. For example, if this is an option with
  `optionTitle` `Large`, its parent variant has `optionTitle` `Red`, and the product
  `title` is `Fancy T-Shirt`, then this `title` will be something like `Fancy T-Shirt - Red - Large`.
  """
  title: String

  "The date and time at which this CatalogProduct was last updated, which is when the related product was most recently published"
  updatedAt: DateTime

  "The related Variant ID"
  variantId: ID!

  "The weight of the product on Earth, if it has physical dimensions"
  weight: Float

  "The width of the product, if it has physical dimensions"
  width: Float
}

"""
Catalog items are combined to create a catalog. Each item can represent a different type of content.
"""
interface CatalogItem {
  "Item ID"
  _id: ID!

  "Date and time at which the item was created"
  createdAt: DateTime

  "Shop that owns the item"
  shop: Shop!

  "Date and time at which the item was last updated"
  updatedAt: DateTime
}

"Represents a catalog item that displays a product"
type CatalogItemProduct implements CatalogItem & Node {
  "The CatalogItemProduct ID"
  _id: ID!

  "The date and time at which this CatalogItem was first created, which is when the related product was first published"
  createdAt: DateTime!

  "The catalog product"
  product: CatalogProduct

  "The shop to which this catalog belongs"
  shop: Shop!

  "The date and time at which this CatalogItem was last updated, which is when the related product was most recently published"
  updatedAt: DateTime!
}

"Represents a catalog item that displays some non-product content"
type CatalogItemContent implements CatalogItem & Node {
  "The CatalogItemProduct ID"
  _id: ID!

  "The date and time at which this CatalogItem was first created"
  createdAt: DateTime!

  "The shop to which this catalog belongs"
  shop: Shop!

  "The date and time at which this CatalogItem was last updated"
  updatedAt: DateTime!
}

"A connection edge in which each node is a `CatalogItem` object"
type CatalogItemEdge {
  "The cursor that represents this node in the paginated results"
  cursor: ConnectionCursor!

  "The catalog item"
  node: CatalogItem
}

"""
Wraps a list of `CatalogItem`s, providing pagination cursors and information.

For information about what Relay-compatible connections are and how to use them, see the following articles:
- [Relay Connection Documentation](https://facebook.github.io/relay/docs/en/graphql-server-specification.html#connections)
- [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm)
- [Using Relay-style Connections With Apollo Client](https://www.apollographql.com/docs/react/recipes/pagination.html)
"""
type CatalogItemConnection {
  "The list of nodes that match the query, wrapped in an edge to provide a cursor string for each"
  edges: [CatalogItemEdge]

  """
  You can request the `nodes` directly to avoid the extra wrapping that `NodeEdge` has,
  if you know you will not need to paginate the results.
  """
  nodes: [CatalogItem]

  "Information to help a client request the next or previous page"
  pageInfo: PageInfo!

  "The total number of nodes that match your query"
  totalCount: Int!
}

"One product catalog for a particular shop"
type Catalog implements Node {
  "The Catalog ID"
  _id: ID!

  "The date and time at which this Catalog was first created"
  createdAt: DateTime!

  "The shop to which this catalog belongs"
  shop: Shop!

  "The date and time at which this Catalog was last updated"
  updatedAt: DateTime!
}

"Allowed values for sorting catalog items"
enum CatalogItemSortByField {
  "Sort by item ID"
  _id

  "Sort by date and time at which the item was created"
  createdAt

  "Sort in the shop-defined order for the tag filter"
  featured

  "Sort by price"
  minPrice

  "Sort by date and time at which the item was last updated"
  updatedAt
}

type Vendor {
  "The name of the vendor"
  name: String
}

"A connection edge in which each node is a String representing a vendor"
type VendorEdge {
  "The cursor that represents this node in the paginated results"
  cursor: ConnectionCursor!

  "The vendor"
  node: Vendor
}

"""
Wraps an array of vendors, providing pagination cursors and information.

For information about what Relay-compatible connections are and how to use them, see the following articles:
- [Relay Connection Documentation](https://facebook.github.io/relay/docs/en/graphql-server-specification.html#connections)
- [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm)
- [Using Relay-style Connections With Apollo Client](https://www.apollographql.com/docs/react/recipes/pagination.html)
"""
type VendorConnection {
  "The list of nodes that match the query, wrapped in an edge to provide a cursor string for each"
  edges: [VendorEdge]

  """
  You can request the `nodes` directly to avoid the extra wrapping that `NodeEdge` has,
  if you know you will not need to paginate the results.
  """
  nodes: [Vendor]

  "Information to help a client request the next or previous page"
  pageInfo: PageInfo!

  "The total number of nodes that match your query"
  totalCount: Int!
}

extend type Query {
  "Gets items from a shop catalog"
  catalogItems(
    "Provide a list of shop IDs from which you want to get catalog items"
    shopIds: [ID]!

    "Optionally provide a list of tag IDs to further filter the item list"
    tagIds: [ID],

    "Additional filters to apply"
    booleanFilters: [CatalogBooleanFilter],

    "Optional text search query"
    searchQuery: String,

    "Return only results that come after this cursor. Use this with `first` to specify the number of results to return."
    after: ConnectionCursor,

    "Return only results that come before this cursor. Use this with `last` to specify the number of results to return."
    before: ConnectionCursor,

    "Return at most this many results. This parameter may be used with either `after` or `offset` parameters."
    first: ConnectionLimitInt,

    "Return at most this many results. This parameter may be used with the `before` parameter."
    last: ConnectionLimitInt,

    "Return only results that come after the Nth result. This parameter may be used with the `first` parameter."
    offset: Int,

    "Return results sorted in this order"
    sortOrder: SortOrder = desc,

    "Provide a Currency code if sortBy is minPrice"
    sortByPriceCurrencyCode: String

    "By default, items are sorted by when they were last updated, most recently updated first. Set this to sort by one of the other allowed fields"
    sortBy: CatalogItemSortByField = updatedAt
  ): CatalogItemConnection

  "Gets product from catalog"
  catalogItemProduct(
    """
    ID of the shop that owns the catalog product. Not required but highly recommended if you
    have multiple shops and `slugOrId` is a slug because slugs are unique only within a shop.
    """
    shopId: ID

    "Provide either a product ID or slug"
    slugOrId: String
  ): CatalogItemProduct

  "Gets an array of all vendors"
  vendors(
    "Optionally provide a list of shop IDs from which you want to get the vendors"
    shopIds: [ID],

    "Optionally provide a list of tag IDs to further filter the vendors"
    tagIds: [ID],

    "Return only results that come after this cursor. Use this with `first` to specify the number of results to return."
    after: ConnectionCursor,

    "Return only results that come before this cursor. Use this with `last` to specify the number of results to return."
    before: ConnectionCursor,

    "Return at most this many results. This parameter may be used with either `after` or `offset` parameters."
    first: ConnectionLimitInt,

    "Return at most this many results. This parameter may be used with the `before` parameter."
    last: ConnectionLimitInt,

    "Return only results that come after the Nth result. This parameter may be used with the `first` parameter."
    offset: Int,

    "Return results sorted in this order"
    sortOrder: SortOrder = asc
  ): VendorConnection
}

extend type Mutation {
  "Publish products to the Catalog collection by product ID"
  publishProductsToCatalog(
    "Array of Product ID"
    productIds: [ID]!
  ): [CatalogItemProduct]
}
