npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

spapi-listing-builder

v0.1.8

Published

_description_

Downloads

585

Readme

spapi-listing-builder

npm version npm downloads bundle JSDocs License

description

Used to quickly and efficiently generate and validate npm packages that conform to the Amazon SP-API LISTING JSON structure.

install

pnpm install spapi-listing-builder --save

Schema usage

Validate product data through schema

import { SchemaCheck, ListingProduct } from 'spapi-listing-builder'
const schemaCheck = new SchemaCheck(myJsonSchema, {})
const myJsonSchema = JSON.parse(
  fs.readFileSync(path.resolve(__dirname, './schema/HOME.json')).toString(),
)

const listingData = {
  sku: "SKU-1234",
  product_type: "HOME",
  title: "i am product title",
  product_description: "i am product description",
  bullet_points: ["i am bullet point 1", "i am bullet point 2"],
  brand_name: "i am brand name",
  product_identifier_type: "EAN",
  product_identifier_id: "123457689",
  condition: "new_new",
  manufacturer: "your manufacturer",
  manufactuer_id: "9527",
  weight: 1,
  height: 1,
  length: 2,
  width: 3,
  recommendedBrowseNodes: ["123", "456"],
  is_electric: 0,
  search_terms: "i am search terms",
  quantity: 99,
  deal_time: 2,
  sell_price: 66.77,
  country_of_origin: "CN",
  item_type_keyword: "SHOES",
  imgs: [
    {
      type: "Main",
      url: "https://example.com/main.jpg",
    },
    {
      type: "Swatch",
      url: "https://example.com/swatch.jpg",
    },
    {
      type: "PT1",
      url: "https://example.com/pt1.jpg",
    },
  ],
};

const product = new ListingProduct({
  marketplace_id: "ATVPDKIKX0DER",
  data: listingData,
  renderOtherAttributesFn: ({ renderListingArrValue, data }) => {
    return {
      list_price: renderListingArrValue(data.sell_price),
    };
  },
}).main();

const schemaCheck = new SchemaCheck(myJsonSchema, product.attributes).validate();

[
  {
    type: 'error',
    name: 'NoAdditionalPropertiesError',
    code: 'no-additional-properties-error',
    message: 'Additional property `recommended_browse_nodes` in `#` is not allowed',
    data: {
      pointer: '#',
      schema: [Object],
      value: [Object],
      property: 'recommended_browse_nodes',
      properties: [Array]
    }
  },
  {
    type: 'error',
    name: 'RequiredPropertyError',
    code: 'required-property-error',
    message: 'The required property `model_number` is missing at `#`',
    data: {
      key: 'model_number',
      pointer: '#',
      schema: [Object],
      value: [Object]
    }
  },
  ...
]

Generate forms through schema

import { SchemaCheck } from 'spapi-listing-builder'
const schemaCheck = new SchemaCheck(myJsonSchema, {})

// 返回所有schema项的表单
schemaCheck.convert2FormItems()

// 返回schema必填项的表单
schemaCheck.convertRequiredSchema2FormItems()

[{
    "field": "brand",
    "label": "Brand Name",
    "component": "Input",
    "componentProps": {
      "placeholder": "Provide the brand name of the product",
      "max": 100,
      "min": 1
    },
    "required": true
  },
  {
    "field": "bullet_point",
    "label": "Key Product Features",
    "component": "Input",
    "componentProps": {
      "placeholder": "Brief descriptive text, called out via a bullet point, regarding a specific aspect of the product. These display directly under or next to your product photo, it is useful to put interesting information in these fields. Do NOT use all caps or abbreviations. Please do NOT use for fabric content, care instructions or country as these are populated in different fields.",
      "max": 700,
      "min": 0
    },
    "required": true
  },
  {
    "field": "country_of_origin",
    "label": "Country of Publication",
    "component": "Select",
    "componentProps": {
      "placeholder": "Select the product's country of origin",
      "options": [...anyOptions]
    },
    "required": true
  },
  {
    "field": "item_name",
    "label": "Product Name",
    "component": "Input",
    "componentProps": {
      "placeholder": "Provide a title for the item that may be customer facing",
      "max": 200,
      "min": 0
    },
    "required": true
  },
  ...otherItems
]

Listing usage

ListingProduct

import { ListingProduct } from 'spapi-listing-builder'

const listingData = {
  sku: "SKU-1234",
  product_type: "HOME",
  title: "i am product title",
  product_description: "i am product description",
  bullet_points: ["i am bullet point 1", "i am bullet point 2"],
  brand_name: "i am brand name",
  product_identifier_type: "EAN",
  product_identifier_id: "123457689",
  condition: "new_new",
  manufacturer: "your manufacturer",
  manufactuer_id: "9527",
  weight: 1,
  height: 1,
  length: 2,
  width: 3,
  recommendedBrowseNodes: ["123", "456"],
  is_electric: 0,
  search_terms: "i am search terms",
  quantity: 99,
  deal_time: 2,
  sell_price: 66.77,
  country_of_origin: "CN",
  item_type_keyword: "SHOES",
  imgs: [
    {
      type: "Main",
      url: "https://example.com/main.jpg",
    },
    {
      type: "Swatch",
      url: "https://example.com/swatch.jpg",
    },
    {
      type: "PT1",
      url: "https://example.com/pt1.jpg",
    },
  ],
};

new ListingProduct({
    marketplace_id: 'ATVPDKIKX0DER',
    data: listingData,
    renderOtherAttributesFn: ({ renderListingArrValue, data }) => {
    return {
        list_price: renderListingArrValue(data.sell_price),
    }
  },
}).main()

// Result
{
  "productType": "HOME",
  "requirements": "LISTING",
  "attributes": {
    "purchasable_offer": [
      {
        "our_price": [
          {
            "schedule": [
              {
                "value_with_tax": 66.77
              }
            ]
          }
        ]
      }
    ],
    "fulfillment_availability": [
      {
        "fulfillment_channel_code": "DEFAULT",
        "quantity": 99,
        "lead_time_to_ship_max_days": 2
      }
    ],
    "item_name": [
      {
        "value": "i am product title"
      }
    ],
    "manufacturer": [
      {
        "value": "your manufacturer"
      }
    ],
    "item_weight": [
      {
        "unit": "kilograms",
        "value": "1.00"
      }
    ],
    "gift_options": [
      {
        "can_be_messaged": "false",
        "can_be_wrapped": "false"
      }
    ],
    "item_type_keyword": [
      {
        "value": "SHOES"
      }
    ],
    "condition_type": [
      {
        "value": "new_new"
      }
    ],
    "number_of_items": [
      {
        "value": "1"
      }
    ],
    "externally_assigned_product_identifier": [
      {
        "value": "123457689",
        "type": "EAN"
      }
    ],
    "recommended_browse_nodes": [
      [
        {
          "value": "123"
        }
      ],
      [
        {
          "value": "456"
        }
      ]
    ],
    "bullet_point": [
      {
        "value": "i am bullet point 1"
      },
      {
        "value": "i am bullet point 2"
      }
    ],
    "item_package_quantity": [
      {
        "value": "1"
      }
    ],
    "item_dimensions": [
      {
        "height": {
          "unit": "centimeters",
          "value": 1
        },
        "length": {
          "unit": "centimeters",
          "value": 2
        },
        "width": {
          "unit": "centimeters",
          "value": 3
        }
      }
    ],
    "part_number": [
      {
        "value": "9527"
      }
    ],
    "max_order_quantity": [
      {
        "value": "100"
      }
    ],
    "product_description": [
      {
        "value": "i am product description"
      }
    ],
    "supplier_declared_dg_hz_regulation": [
      {
        "value": "not_applicable"
      }
    ],
    "brand": [
      {
        "value": "i am brand name"
      }
    ],
    "generic_keyword": [
      {
        "value": "i am search terms"
      }
    ],
    "country_of_origin": [
      {
        "value": "CN"
      }
    ],
    "main_product_image_locator": [
      {
        "media_location": "https://example.com/main.jpg"
      }
    ],
    "swatch_product_image_locator": [
      {
        "media_location": "https://example.com/swatch.jpg"
      }
    ],
    "other_product_image_locator_1": [
      {
        "media_location": "https://example.com/pt1.jpg"
      }
    ],
    "list_price": [
      {
        "value": "66.77"
      }
    ]
  }
}

ListingQuantity

import { ListingQuantity } from "spapi-listing-builder";

new ListingQuantity({ quantity: 3, deal_time: 2 })

// Result

{
  "op": "replace",
  "path": "/attributes/fulfillment_availability",
  "value": [
    {
      "audience": "ALL",
      "quantity": 3,
      "lead_time_to_ship_max_days": 2
    }
  ]
}

ListingPrice

import { ListingPrice } from "spapi-listing-builder";

new ListingPrice({ sell_price: 100, low_price: 90, max_price: 110 }).main()

// Result

{
  "op": "replace",
  "path": "/attributes/purchasable_offer",
  "value": [
    {
      "audience": "ALL",
      "our_price": [
        {
          "schedule": [
            {
              "value_with_tax": 100
            }
          ]
        }
      ],
      "minimum_seller_allowed_price": [
        {
          "schedule": [
            {
              "value_with_tax": 90
            }
          ]
        }
      ],
      "maximum_seller_allowed_price": [
        {
          "schedule": [
            {
              "value_with_tax": 110
            }
          ]
        }
      ]
    }
  ]
}

ListingImg

import { ListingImg } from "spapi-listing-builder";

new ListingImg([
    { type: 'Main', url: 'http://main.jpg' },
    { type: 'Swatch', url: 'http://thumb.jpg' },
]).main()

// Result

[
  {
    "op": "replace",
    "path": "/attributes/main_product_image_locator",
    "value": [
      {
        "media_location": "http://main.jpg"
      }
    ]
  },
  {
    "op": "replace",
    "path": "/attributes/swatch_product_image_locator",
    "value": [
      {
        "media_location": "http://thumb.jpg"
      }
    ]
  }
]

ListingRelation

import { ListingRelation } from "spapi-listing-builder";

new ListingRelation('parent_sku123').main()

// Result

{
  "op": "replace",
  "path": "/attributes/child_parent_sku_relationship",
  "value": [
    {
      "child_relationship_type": "variation",
      "parent_sku": "parent_sku123"
    }
  ]
}

Feed usage

FeedProduct

import { FeedProduct } from 'spapi-listing-builder'

new FeedProduct('sellerId', 'ATVPDKIKX0DER', [listingData, parentListingData])

// Result

{
  "header": {
    "sellerId": "sellerId",
    "version": "2.0",
    "issueLocale": "en_US"
  },
  "messages": [
    {
      "messageId": 1,
      "sku": "SKU-1234",
      "operationType": "UPDATE",
      "productType": "HOME",
      "requirements": "LISTING",
      "attributes": listingDataAttributes
    },
    {
      "messageId": 2,
      "sku": "SKU-parent01",
      "operationType": "UPDATE",
      "productType": "HOME",
      "requirements": "LISTING",
      "attributes": parentListingDataAttributes
    }
  ]
}

FeedQuantity

import { FeedQuantity } from 'spapi-listing-builder'

new FeedQuantity('sellerId', [{ sku: 'sku-1', quantity: 100, deal_time: 3 }])

// Result
{
  "header": {
    "sellerId": "sellerId",
    "version": "2.0",
    "issueLocale": "en_US"
  },
  "messages": [
    {
      "messageId": 1,
      "sku": "sku-1",
      "operationType": "PATCH",
      "productType": "PRODUCT",
      "patches": [
        {
          "op": "replace",
          "path": "/attributes/fulfillment_availability",
          "value": [
            {
              "fulfillment_channel_code": "DEFAULT",
              "quantity": 100,
              "lead_time_to_ship_max_days": 3
            }
          ]
        }
      ]
    }
  ]
}

FeedPrice

import { FeedPrice } from 'spapi-listing-builder'

new FeedPrice('sellerId', [{ country_code: 'us', sku: 'sku-1', sell_price: 100 }])

// Result
{
  "header": {
    "sellerId": "sellerId",
    "version": "2.0",
    "issueLocale": "en_US"
  },
  "messages": [
    {
      "messageId": 1,
      "sku": "sku-1",
      "operationType": "PATCH",
      "productType": "PRODUCT",
      "patches": [
        {
          "op": "replace",
          "path": "/attributes/purchasable_offer",
          "value": [
            {
              "audience": "ALL",
              "our_price": [
                {
                  "schedule": [
                    {
                      "value_with_tax": 100
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

FeedImg

import { FeedImg } from 'spapi-listing-builder'

new FeedImg('sellerId', [
    {
      sku: 'sku-1',
      imgs: [
        { type: 'Main', url: 'http://main.jpg' },
        { type: 'Swatch', url: 'http://thumb.jpg' },
      ],
    },
])

// Result
{
  "header": {
    "sellerId": "sellerId",
    "version": "2.0",
    "issueLocale": "en_US"
  },
  "messages": [
    {
      "messageId": 1,
      "sku": "sku-1",
      "operationType": "PATCH",
      "productType": "PRODUCT",
      "patches": [
        {
          "op": "replace",
          "path": "/attributes/main_product_image_locator",
          "value": [
            {
              "media_location": "http://main.jpg"
            }
          ]
        },
        {
          "op": "replace",
          "path": "/attributes/swatch_product_image_locator",
          "value": [
            {
              "media_location": "http://thumb.jpg"
            }
          ]
        }
      ]
    }
  ]
}

FeedRelation

import { FeedRelation } from 'spapi-listing-builder'

new FeedRelation('sellerId', [
  { sku: 'child-sku', parent_sku: 'parent_sku-123' }
])

// Result
{
  "header": {
    "sellerId": "sellerId",
    "version": "2.0",
    "issueLocale": "en_US"
  },
  "messages": [
    {
      "messageId": 1,
      "sku": "child-sku",
      "operationType": "PATCH",
      "productType": "LUGGAGE",
      "patches": [
        {
          "op": "replace",
          "path": "/attributes/child_parent_sku_relationship",
          "value": [
            {
              "child_relationship_type": "variation",
              "parent_sku": "parent_sku-123"
            }
          ]
        }
      ]
    }
  ]
}

utils

renderListingArrValue


import { renderListingArrValue } from 'spapi-listing-builder'

renderListingArrValue('test')

// Result
[
  {
    "value": "test"
  }
]

renderListingArrValue(true)

// Result
[
  {
    "value": 'true'
  }
]

renderListingArrValue({
  height: {
    unit: 'centimeters',
    value: 1,
  },
  length: {
    unit: 'centimeters',
    value: 2,
  },
  width: {
    unit: 'centimeters',
    value: 3,
  },
})

// Result
[
  {
    height: {
      unit: 'centimeters',
      value: 1,
    },
    length: {
      unit: 'centimeters',
      value: 2,
    },
    width: {
      unit: 'centimeters',
      value: 3,
    },
  },
]

Reference

License

MIT License © 2024-PRESENT wangjue666