From dbc58418efeba748ccfbadf0ebf000ecfc7a44bd Mon Sep 17 00:00:00 2001 From: Thor Date: Fri, 3 May 2019 15:22:17 +0200 Subject: [PATCH] Node: Decouple product setup. (#70) * Make server/node/setup.js standalone script. * Remove product exist checking which relies on hardcoded product names. * Run product setup script on postinstall hook. --- package.json | 4 +- public/javascripts/store.js | 5 ++ server/node/inventory.js | 13 ---- server/node/routes.js | 11 +--- server/node/setup.js | 126 ++++++++++++++++-------------------- 5 files changed, 65 insertions(+), 94 deletions(-) diff --git a/package.json b/package.json index e5560b23..3afa48d4 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "node": "8.x" }, "scripts": { - "start": "node server/node/server.js" + "start": "node server/node/server.js", + "setup-products": "node server/node/setup.js", + "postinstall": "npm run setup-products" }, "dependencies": { "body-parser": "^1.17.1", diff --git a/public/javascripts/store.js b/public/javascripts/store.js index 4f53c6b4..6ce60c76 100644 --- a/public/javascripts/store.js +++ b/public/javascripts/store.js @@ -71,6 +71,11 @@ class Store { this.productsFetchPromise = new Promise(async resolve => { const productsResponse = await fetch('/products'); const products = (await productsResponse.json()).data; + if (!products.length) { + throw new Error( + 'No products on Stripe account! Make sure the setup script has run properly.' + ); + } // Check if we have SKUs on the product, otherwise load them separately. for (const product of products) { this.products[product.id] = product; diff --git a/server/node/inventory.js b/server/node/inventory.js index 693ef6a5..f724b554 100644 --- a/server/node/inventory.js +++ b/server/node/inventory.js @@ -25,18 +25,6 @@ const retrieveProduct = async productId => { return await stripe.products.retrieve(productId); }; -// Validate that products exist. -const productsExist = productList => { - const validProducts = ['increment', 'shirt', 'pins']; - return productList.data.reduce((accumulator, currentValue) => { - return ( - accumulator && - productList.data.length === 3 && - validProducts.includes(currentValue.id) - ); - }, !!productList.data.length); -}; - // Get shipping cost from config based on selected shipping option. const getShippingCost = shippingOption => { return config.shippingOptions.filter( @@ -47,6 +35,5 @@ const getShippingCost = shippingOption => { exports.products = { list: listProducts, retrieve: retrieveProduct, - exist: productsExist, getShippingCost, }; diff --git a/server/node/routes.js b/server/node/routes.js index 340ac3fb..88181eec 100644 --- a/server/node/routes.js +++ b/server/node/routes.js @@ -11,7 +11,6 @@ 'use strict'; const config = require('./config'); -const setup = require('./setup'); const {products} = require('./inventory'); const express = require('express'); const router = express.Router(); @@ -192,15 +191,7 @@ router.get('/config', (req, res) => { // Retrieve all products. router.get('/products', async (req, res) => { - const productList = await products.list(); - // Check if products exist on Stripe Account. - if (products.exist(productList)) { - res.json(productList); - } else { - // We need to set up the products. - await setup.run(); - res.json(await products.list()); - } + res.json(await products.list()); }); // Retrieve a product by ID. diff --git a/server/node/setup.js b/server/node/setup.js index 9c11255c..3f75d421 100644 --- a/server/node/setup.js +++ b/server/node/setup.js @@ -13,76 +13,62 @@ const config = require('./config'); const stripe = require('stripe')(config.stripe.secretKey); stripe.setApiVersion(config.stripe.apiVersion); -module.exports = { - running: false, - run: async () => { - if (this.running) { - console.log('⚠️ Setup already in progress.'); - } else { - this.running = true; - this.promise = new Promise(async resolve => { - // Create a few products and SKUs assuming they don't already exist. - try { - // Increment Magazine. - const increment = await stripe.products.create({ - id: 'increment', - type: 'good', - name: 'Increment Magazine', - attributes: ['issue'], - }); - await stripe.skus.create({ - id: 'increment-03', - product: 'increment', - attributes: {issue: 'Issue #3 “Development”'}, - price: 399, - currency: config.currency, - inventory: {type: 'infinite'}, - }); +// Replace this list with information about your store's products. +const products = [ + { + id: 'increment', + name: 'Increment Magazine', + price: 399, + attributes: {issue: 'Issue #3 “Development”'}, + }, + { + id: 'shirt', + name: 'Stripe Shirt', + price: 999, + attributes: {size: 'Small Standard', gender: 'Woman'}, + }, + { + id: 'pins', + name: 'Stripe Pins', + price: 799, + attributes: {set: 'Collector Set'}, + }, +]; - // Stripe Shirt. - const shirt = await stripe.products.create({ - id: 'shirt', - type: 'good', - name: 'Stripe Shirt', - attributes: ['size', 'gender'], - }); - await stripe.skus.create({ - id: 'shirt-small-woman', - product: 'shirt', - attributes: {size: 'Small Standard', gender: 'Woman'}, - price: 999, - currency: config.currency, - inventory: {type: 'infinite'}, - }); +// Creates a collection of Stripe Products and SKUs to use in your storefront +const createStoreProducts = async () => { + try { + const stripeProducts = await Promise.all( + products.map(async product => { + const stripeProduct = await stripe.products.create({ + id: product.id, + name: product.name, + type: 'good', + attributes: Object.keys(product.attributes), + metadata: product.metadata, + }); - // Stripe Pins. - const pins = await stripe.products.create({ - id: 'pins', - type: 'good', - name: 'Stripe Pins', - attributes: ['set'], - }); - await stripe.skus.create({ - id: 'pins-collector', - product: 'pins', - attributes: {set: 'Collector Set'}, - price: 799, - currency: config.currency, - inventory: {type: 'finite', quantity: 500}, - }); - console.log('Setup complete.'); - resolve(); - this.running = false; - } catch (err) { - if (err.message === 'Product already exists.') { - console.log('⚠️ Products have already been registered.'); - console.log('Delete them from your Dashboard to run this setup.'); - } else { - console.log('⚠️ An error occurred.', err); - } - } - }); - } - return this.promise; - }, + const stripeSku = await stripe.skus.create({ + product: stripeProduct.id, + price: product.price, + currency: config.currency, + attributes: product.attributes, + inventory: {type: 'infinite'}, + }); + + return {stripeProduct, stripeSku}; + }) + ); + + console.log( + `🛍️ Successfully created ${ + stripeProducts.length + } products on your Stripe account.` + ); + } catch (error) { + console.log(`⚠️ Error: ${error.message}`); + return; + } }; + +createStoreProducts();