diff --git a/.env.template b/.env.template index 7d8400baf..9b45afe4b 100644 --- a/.env.template +++ b/.env.template @@ -3,5 +3,7 @@ BIGCOMMERCE_STOREFRONT_API_TOKEN= BIGCOMMERCE_STORE_API_URL= BIGCOMMERCE_STORE_API_TOKEN= BIGCOMMERCE_STORE_API_CLIENT_ID= +BIGCOMMERCE_CHANNEL_ID= + SHOPIFY_STORE_DOMAIN= -SHOPIFY_STOREFRONT_ACCESS_TOKEN= \ No newline at end of file +SHOPIFY_STOREFRONT_ACCESS_TOKEN= diff --git a/README.md b/README.md index 9d2108cfe..f254b1b07 100644 --- a/README.md +++ b/README.md @@ -77,12 +77,12 @@ Main folder and its exposed functions - `config.json` - README.md -#### Example of correct usage of Commece Framework +#### Example of correct usage of Commerce Framework ```js import { useUI } from '@components/ui' import { useCustomer } from '@framework/customer' -import { useAddItem, useWishlist, useRemoveItem } from '@framework/wishlist' +import { useWishlist, useAddItem, useRemoveItem } from '@framework/wishlist' ``` ## Config @@ -131,6 +131,7 @@ BIGCOMMERCE_STOREFRONT_API_TOKEN=<> BIGCOMMERCE_STORE_API_URL=<> BIGCOMMERCE_STORE_API_TOKEN=<> BIGCOMMERCE_STORE_API_CLIENT_ID=<> +BIGCOMMERCE_CHANNEL_ID=<> ``` If your project was started with a "Deploy with Vercel" button, you can use Vercel's CLI to retrieve these credentials. diff --git a/framework/bigcommerce/README.md b/framework/bigcommerce/README.md index 86fbac91d..2609b1544 100644 --- a/framework/bigcommerce/README.md +++ b/framework/bigcommerce/README.md @@ -47,6 +47,7 @@ BIGCOMMERCE_STOREFRONT_API_TOKEN=<> BIGCOMMERCE_STORE_API_URL=<> BIGCOMMERCE_STORE_API_TOKEN=<> BIGCOMMERCE_STORE_API_CLIENT_ID=<> +BIGCOMMERCE_CHANNEL_ID=<> ``` ## General Usage diff --git a/framework/bigcommerce/next.config.js b/framework/bigcommerce/next.config.js index e732ef78a..5703f2343 100644 --- a/framework/bigcommerce/next.config.js +++ b/framework/bigcommerce/next.config.js @@ -1,37 +1,11 @@ +const providerConfig = require('./config.json') + module.exports = { + commerce: { + provider: 'bigcommerce', + ...providerConfig, + }, images: { domains: ['cdn11.bigcommerce.com'], }, - i18n: { - locales: ['en-US', 'es'], - defaultLocale: 'en-US', - }, - rewrites() { - return [ - { - source: '/checkout', - destination: '/api/bigcommerce/checkout', - }, - // The logout is also an action so this route is not required, but it's also another way - // you can allow a logout! - { - source: '/logout', - destination: '/api/bigcommerce/customers/logout?redirect_to=/', - }, - // Rewrites for /search - { - source: '/search/designers/:name', - destination: '/search', - }, - { - source: '/search/designers/:name/:category', - destination: '/search', - }, - { - // This rewrite will also handle `/search/designers` - source: '/search/:category', - destination: '/search', - }, - ] - }, } diff --git a/framework/commerce/types.ts b/framework/commerce/types.ts index 57e707f35..bf635c9dc 100644 --- a/framework/commerce/types.ts +++ b/framework/commerce/types.ts @@ -2,12 +2,6 @@ import type { Wishlist as BCWishlist } from '@framework/api/wishlist' import type { Customer as BCCustomer } from '@framework/api/customers' import type { SearchProductsData as BCSearchProductsData } from '@framework/api/catalog/products' -export type Features = 'wishlist' | 'checkout' | string - -export type CommerceProviderConfig = { - features: Record -} - export type Discount = { // The value of the discount, can be an amount or percentage value: number diff --git a/framework/commerce/utils/bootstrap.js b/framework/commerce/utils/bootstrap.js deleted file mode 100644 index 6a604b7dd..000000000 --- a/framework/commerce/utils/bootstrap.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = ({ features }) => { - let output = { - env: {}, - } - if (!!Object.keys(features).length) { - Object.keys(features).map( - (r) => (output.env[`COMMERCE_${r.toUpperCase()}_ENABLED`] = features[r]) - ) - } - return output -} diff --git a/framework/commerce/utils/features.ts b/framework/commerce/utils/features.ts deleted file mode 100644 index 72ed0d7f5..000000000 --- a/framework/commerce/utils/features.ts +++ /dev/null @@ -1,47 +0,0 @@ -import commerceProviderConfig from '../config.json' -import type { CommerceProviderConfig } from '../types' -import memo from 'lodash.memoize' - -type FeaturesAPI = { - isEnabled: (desideredFeature: string) => boolean -} - -function isFeatureEnabled(config: CommerceProviderConfig) { - const features = config.features - return (desideredFeature: string) => - Object.keys(features) - .filter((k) => features[k]) - .includes(desideredFeature) -} - -export function toEnvConfig( - configMap: CommerceProviderConfig['features'] -): Map { - let toEnvConfigMap = new Map() - Object.keys(configMap).map((r) => - toEnvConfigMap.set(`${r.toUpperCase()}_ENABLED`, configMap[r]) - ) - return toEnvConfigMap -} - -function boostrap(): FeaturesAPI { - const basis = { - isEnabled: () => false, - } - - if (!commerceProviderConfig) { - console.log('No config.json found - Please add a config.json') - return basis - } - - if (commerceProviderConfig.features) { - return { - ...basis, - isEnabled: memo(isFeatureEnabled(commerceProviderConfig)), - } - } - - return basis -} - -export default boostrap() diff --git a/framework/commerce/with-config.js b/framework/commerce/with-config.js new file mode 100644 index 000000000..6dcf08986 --- /dev/null +++ b/framework/commerce/with-config.js @@ -0,0 +1,40 @@ +/** + * This file is expected to be used in next.config.js only + */ + +const merge = require('deepmerge') + +const PROVIDERS = ['bigcommerce'] + +function getProviderName() { + return process.env.BIGCOMMERCE_STOREFRONT_API_URL ? 'bigcommerce' : null +} + +module.exports = (nextConfig = {}) => { + const commerce = nextConfig.commerce || {} + const name = commerce.provider || getProviderName() + + if (!name) { + throw new Error( + `The commerce provider is missing, please add a valid provider name or its environment variables` + ) + } + if (!PROVIDERS.includes(name)) { + throw new Error( + `The commerce provider "${name}" can't be found, please use one of "${PROVIDERS.join( + ', ' + )}"` + ) + } + + const commerceNextConfig = require(`../${name}/next.config`) + const config = merge(commerceNextConfig, nextConfig) + + config.env = config.env || {} + + Object.entries(config.commerce.features).forEach(([k, v]) => { + if (v) config.env[`COMMERCE_${k.toUpperCase()}_ENABLED`] = true + }) + + return config +} diff --git a/next.config.js b/next.config.js index 749fd1b0a..725024066 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,40 @@ -const providerConfig = require('./framework/bigcommerce/config.json') -const providerNextConfig = require('./framework/bigcommerce/next.config') -const bootstrap = require('./framework/commerce/utils/bootstrap') -const d = require('deepmerge') +const withCommerceConfig = require('./framework/commerce/with-config') -module.exports = d(providerNextConfig, bootstrap(providerConfig)) +const commerce = { provider: 'bigcommerce' } +const isBC = commerce.provider === 'bigcommerce' + +module.exports = withCommerceConfig({ + commerce, + i18n: { + locales: ['en-US', 'es'], + defaultLocale: 'en-US', + }, + rewrites() { + return [ + isBC && { + source: '/checkout', + destination: '/api/bigcommerce/checkout', + }, + // The logout is also an action so this route is not required, but it's also another way + // you can allow a logout! + isBC && { + source: '/logout', + destination: '/api/bigcommerce/customers/logout?redirect_to=/', + }, + // Rewrites for /search + { + source: '/search/designers/:name', + destination: '/search', + }, + { + source: '/search/designers/:name/:category', + destination: '/search', + }, + { + // This rewrite will also handle `/search/designers` + source: '/search/:category', + destination: '/search', + }, + ].filter((x) => x) + }, +}) diff --git a/package.json b/package.json index 85bd9c063..d2ed966c3 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ }, "dependencies": { "@reach/portal": "^0.11.2", - "@types/lodash.memoize": "^4.1.6", "@vercel/fetch": "^6.1.0", "body-scroll-lock": "^3.1.5", "bowser": "^2.11.0", @@ -34,7 +33,6 @@ "js-cookie": "^2.2.1", "keen-slider": "^5.2.4", "lodash.debounce": "^4.0.8", - "lodash.memoize": "^4.1.2", "lodash.random": "^3.2.0", "lodash.throttle": "^4.1.1", "next": "^10.0.7-canary.3", diff --git a/yarn.lock b/yarn.lock index 1255b9d62..c6114e0f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1060,13 +1060,6 @@ dependencies: "@types/lodash" "*" -"@types/lodash.memoize@^4.1.6": - version "4.1.6" - resolved "https://registry.yarnpkg.com/@types/lodash.memoize/-/lodash.memoize-4.1.6.tgz#3221f981790a415cab1a239f25c17efd8b604c23" - integrity sha512-mYxjKiKzRadRJVClLKxS4wb3Iy9kzwJ1CkbyKiadVxejnswnRByyofmPMscFKscmYpl36BEEhCMPuWhA1R/1ZQ== - dependencies: - "@types/lodash" "*" - "@types/lodash.random@^3.2.6": version "3.2.6" resolved "https://registry.yarnpkg.com/@types/lodash.random/-/lodash.random-3.2.6.tgz#64b08abad168dca39c778ed40cce75b2f9e168eb" @@ -4244,11 +4237,6 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"