Code Monkey home page Code Monkey logo

front-commerce / developers.front-commerce.com Goto Github PK

View Code? Open in Web Editor NEW
12.0 2.0 7.0 190.01 MB

Front-Commerce is an agnostic frontend for ecommerce based on headless commerce & modern technologies: NodeJS, React, GraphQL. Our frontend connects to leading backends like Magento or BigCommerce with total coverage, & integrates seamlessly with solutions including Prismic, Contentful, TwicPics, Adyen, Stripe, Algolia.

Home Page: https://developers.front-commerce.com/

License: MIT License

JavaScript 0.58% TypeScript 2.17% CSS 0.50% MDX 96.75%
dx e-commerce front-end performance react

developers.front-commerce.com's Introduction

Front-Commerce — Developers area

Netlify Status

This is the source code for the https://developers.front-commerce.com website.

Please use Github issues and PR for feedbacks, suggestions and improvements.

License

This contents in this repository is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.

The code though is under MIT License.

Installation

$ npm install

Local Development

$ npm start

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

Build

$ npm build

This command generates static content into the build directory and can be served using any static contents hosting service.

Run

$ npm serve

This command generates static content into the build directory and can be served using any static contents hosting service.

developers.front-commerce.com's People

Contributors

abailleulfc avatar aerowiel avatar bastienlm avatar dependabot[bot] avatar dpobel avatar gkueny avatar haltarys avatar julienpradet avatar kagaminara avatar mggk-fr avatar mo-fc avatar paul-vd avatar rachaelfrontcommerce avatar real34 avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

developers.front-commerce.com's Issues

Document how to interact with Magento2’s REST API

Gather documentation from our old tools, and update this issue with relevant documentation information before adding them to official developers documentation.

Goal: allow developers to interact with exposed REST API from Magento2 modules


Here are some notes:

  • When M2.3 will have been integrated (and if it seems relevant) recommend to implement a GraphQL API directly so it could be proxied directly (+ write another documentation page to explain how)
  • Fallbacks when logged out (to refresh a token)
  • scopes (Magento)
  • admin API (integration)
// src/server/model/magento2Connector/factories.js
module.exports = {
  makeUserClientFromRequest,
  makeAdminClientFromRequest,
  makeAuthServiceFromRequest,
  makeSearchDataSourceFromRequest,
  makeCartUrlBuilderFromRequest,
  makeStoreConfigFromRequest
};
const {
  makeUserClientFromRequest,
  makeAuthServiceFromRequest
} = require("../magento2Connector/factories");

    const axiosInstance = makeUserClientFromRequest(
      config.magentoEndpoint,
      req
    );
    const authService = makeAuthServiceFromRequest(req);

Ensure business component example works with SSR

The https://developers.front-commerce.com/docs/essentials/create-a-business-component.html tutoriel seems to not be SSR compliant.

We should ensure it works either by using react-leaflet-universal or branchServerClient.

tout à l'heure quand j'ai commencé à faire l'exemple de la doc avec le store locator j'ai eu une erreur liée à la lib leaflet
Enfin react-leaflet plutôt apparemment elle ne gère pas le SSR
Du coup j'ai installé une autre lib, react-leaflet-universal
Et dans l'import j'ai juste remplacé

import { Map, TileLayer, Marker, Popup } from "react-leaflet";

par

import { Map, TileLayer, Marker, Popup } from "react-leaflet-universal";

Je pense que ce sera à retester, peut-être que le problème pouvait être résolé autrement mais au cas où

Document Troubleshooting about authentification

There can be many footguns when it comes to authentication. We should provide the list of the things we do to make sure that everything is well configured. If this could be automated, it would be even more awesome obviously.

Things that comes to mind right now:

  • cookie domain FRONT_COMMERCE_COOKIE_DOMAIN (< 1.0.0-beta.6)
  • secure/unsecure cookie
    • production is https only
    • but a proxy needs to forward the necessayr infos used (X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port) (DEBUG=front-commerce:config and go to /__front-commerce/debug url)
  • any platform specificities? Magento2? Magento1?

Payment methods: document how to setup each method

Gather documentation from our old tools, and update this issue with relevant documentation information before adding them to official developers documentation.

List all the supported payment methods and how to configure them (in payment backoffice, magento admin, service keys, etc.)


Some notes:

Front-Commerce embedded payments modules

Front-Commerce can handle payments directly with its middleware, without the need for a payment integration in your e-commerce system.

We provide the necessary payment method implementation for your eCommerce solution, so that you can still benefit from order management and workflows.

For your eCommerce system, a payment made with Front-Commerce is integrated in a similar way than checks / wire payments (sometimes named "offline payment"). The difference is that due to possible API integrations, Front-Commerce will still mark the order payment as validated upon receiving automatic notifications from the payment service.

WARNING: TODO - Add an architecture graph here

Below are the existing Front-Commerce payment modules.

Production ready

The modules below are used in production and ready for use.

Working

The modules below have been developed and are ready for use, but not yet used in production by customers.

Started

The modules below have been started but are still in progress.

  • PayZen - paused due to unfinished remote API and no more use case

Planned

The modules below are planned to be implemented in our roadmap. Please contact us if you need a payment to be supported.

  • Stripe

TODO Document configuration

Magento2 supported modules

The Magento2 modules below are supported by Front-Commerce’s core. Configuration is the same than for a standard Magento installation.

Production ready

The modules below are used in production and ready for use.

Working

The modules below have been developed and are ready for use, but not yet used in production by customers.

Document testing utils

In a recent Pull Request, I've added a mock implementation of a dataloader to test a certain behavior of one of my loader. We should document these kind of mock/helpers functions dedicated to testing.

@real34 mentioned that we could add a Testing section containing these kinds of things.

So let's do this! :)


A few notes about the mock implementation of a dataloader :

import {
  createLoader,
  hasMockDataloaderCache,
  resetAllMockDataloaders
} from "src/server/core/cache/strategies/mock.js";
  • createLoader behaves exactly like the memoize.createLoader
  • hasMockDataloaderCache(key, id) lets you know if a certain value is already cached for a particular dataloader
  • resetAllMockDataloaders resets all your dataloaders (you usually want to call this function before/after each test.

Migration guides: dead link

URL: https://developers.front-commerce.com/docs/

Last but not least, if you are upgrading a project to the latest Front-Commerce version, we have documented some Migration guides to make the process as seamless as possible.

The link on Migration guides leads to https://developers.front-commerce.com/docs/migration-guides.md but throws a 404 error.

Add simple examples

Hi,
A lot of my everyday uses are not in the documentation, ie:

  • how to add a product/customer/category attribute?
  • how to get the current customer?

In summary, it would be nice to have some "real life" code snippets.

Webperfs improvement

We have been focused on the content so far, but the homepage is horrible in terms of webperfs!

Images are heavy, JS is sync, fonts are served from the Google CDN…

At some point it would be great to take some time to improve this a little.

Payment in Front-Commerce

Gather documentation from our old tools, and update this issue with relevant documentation information before adding them to official developers documentation.

Goal: explain the different types of payments (embed, redirect, etc.)


Notes/Draft:

Payment methods

Front-Commerce provides different hooks allowing to use the payment method of your choice.
This section explains the high-level payment flows supported, and documents the mechanisms available to implement your own custom method if existing payment modules do not suit your needs.

Payment workflows

Front-Commerce has a concept of « payment workflow » to model a payment scenario from a customer standpoint. This is a core concept to understand for anyone wanting to create a really custom checkout or implement a new payment method.

So far, 3 workflows are supported and are explained below:

  • « Direct Order »
  • « Redirect After Order »
  • « Redirect Before Order »

Direct Order

Examples: check, wire payments, free…

When Customers select the payment method and finish the checkout process, their order is placed immediately without any extra payment step involved and they are redirected on the checkout success page.

Redirect After Order

Examples: traditional credit cards

When Customers select the payment method and finish the checkout process, their order is placed in a « pending payment » state and they are redirected on the bank website. Upon successful payment, the order is marked as paid and Customers are redirected on the checkout success page.

Redirect Before Order

Examples: Paypal Express Checkout

When Customers select the payment method, they can be redirected to the payment platform at any time and authorize a payment matching their Cart total. When they are back on the shop, the order can be placed and the payment captured synchronously. Customers are then redirected on the checkout success page.

Front-Commerce embedded payments

…… TODO ……

Embedded payments, per their nature follow the « Direct Order » payment workflow.

Register a new embedded payment

New embedded payment methods have to be registered from a GraphQL module. Let’s create a new « PWAy » payment module.

  • Create a new GraphQL module
  • Add a depency upon "Magento2/Checkout"
module.exports = {
  namespace: "Payments/PWAy",
  dependencies: ["Magento2/Checkout"]
};
  • Register the payment method from the module’s contextEnhancer
module.exports = {
  namespace: "Payments/PWAy",
  dependencies: ["Magento2/Checkout"],
  contextEnhancer: ({ loaders }) => {
    // [...] initialization here

    const chargeTransactionForOrder = (paymentData, orderId) => {
       /* … the actual code that will charge the transaction (might delegate to a loader) … */
    };

    const METHOD_CODE = "pway_awesomecheckout";
    const METHOD_TITLE = "PWAy";
    loaders.Payment.registerEmbeddedPaymentMethod(
      METHOD_CODE,
      METHOD_TITLE,
      chargeTransactionForOrder
    );

    return {}; // you may export loaders here in case the payment provides custom Queries (to fetch a payment token for instance)
  }
};

Magento2 payments

In its current state, Magento2 does not support headless payments. Payment modules hence often rely on the CheckoutSession or CustomerSession to persist meaningful information across checkout steps.

Front-Commerce’s Magento module provides a generic way to expose Magento payment modules headlessly and supports the payment flows described above.

This section explains the mechanisms available to implement your own adapter if supported Magento payment modules do not suit your needs.

Create a Payment Adapter

Payment Adapters must implement the \FrontCommerce\Integration\Api\HeadlessPayment\Adapter interface no matter the flows they support.

Front-Commerce module will simulate a Magento action as if the page was loaded in a frontend context. It will:

  1. create a and RequestInterface instance
  2. dispatch the request through Magento’s Front Controller
  3. converts the response into a Front-Commerce headless API response

Adapters must implement methods that are called at key times in order to allow to initialize the request or convert a response properly depending on the payment module internal implementations.

<?php

namespace FrontCommerce\Integration\Api\HeadlessPayment;

use FrontCommerce\Integration\Api\Data\HeadlessPayment\RedirectionInterface;
use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Checkout\Model\Session as CheckoutSession;
use Magento\Customer\Model\Session as CustomerSession;
use Magento\Framework\App\Response\HttpInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\HTTP\PhpEnvironment\Response;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\View\Element\BlockFactory;
use Magento\Quote\Model\Quote\Payment;
use Magento\Sales\Model\Order;

interface Adapter
{
    /**
     * Convert internal Magento response to a `RedirectionInterface` value object
     *
     * Payment Flow: redirect before order
     *
     * @param Response $response
     * @param ManagerInterface $messagesManager
     * @return RedirectionInterface
     */
    public function redirectionFromCheckoutRedirectActionResponse(
        Response $response,
        ManagerInterface $messagesManager
    ): RedirectionInterface;

    /**
     * Convert internal Magento response to a `RedirectionInterface` value object
     *
     * Payment Flow: redirect after order
     *
     * @param Response $response
     * @param ManagerInterface $messagesManager
     * @return RedirectionInterface
     */
    public function redirectionFromCheckoutRedirectAfterActionResponse(
        Response $response,
        ManagerInterface $messagesManager
    ): RedirectionInterface;

    /**
     * Populate session objects with information required by the payment action
     *
     * Payment Flow: redirect after order
     *
     * @param CheckoutSession $checkoutSession
     * @param CustomerSession $customerSession
     * @param Order $order
     * @return void
     */
    public function prepareAfterCheckoutContext(
        CheckoutSession $checkoutSession,
        CustomerSession $customerSession,
        Order $order
    );

    /**
     * Return the url that will be dispatched internally to trigger the redirection
     * to the payment provider in the payment module
     *
     * Payment Flows:
     *  - redirect before order
     *  - redirect after order
     *
     * @param ConfigProviderInterface $configProvider
     * @param Payment|null $payment
     * @return string
     */
    public function checkoutRedirectUrl(
        ConfigProviderInterface $configProvider,
        Payment $payment = null
    ): string;

    /**
     * Populate/change the Magento response object while still in the correct store context.
     * For instance: render blocks…
     *
     * Payment Flow: redirect after order
     *
     * @param HttpInterface $response
     * @param BlockFactory $blockFactory
     * @param ResultInterface|null $result
     * @param ObjectManagerInterface $objectManager
     * @return mixed
     */
    public function changeAfterCheckoutResponseFromResult(
        HttpInterface $response,
        BlockFactory $blockFactory,
        ResultInterface $result = null,
        ObjectManagerInterface $objectManager
    );

    /**
     * Factory to build a `ProxiedAction` matching the next step for the Customer
     * depending on information transmitted by the payment system in the return url
     * the user was redirected to when coming back to the store
     * 
     * Payment Flows:
     *  - redirect before order
     *  - redirect after order
     *
     * @param string $actionName
     * @param array $additionalData
     * @param null $customerId
     * @return ProxiedAction
     */
    public function buildReturnFromPlatformProxiedAction(
        string $actionName,
        array $additionalData,
        $customerId = null
    ): ProxiedAction;
}

Note: in case an action is not supported, we recommend to throw an exception so Front-Commerce could gracefully prevent the checkout process by displaying a relevant information to the Customer.
Example: throw new \RuntimeException('Checkout flow not supported');

Register the Payment Adapter

Using the di.xml inject the adapter in the FrontCommerce\Integration\Model\HeadlessPayments\AdapterFactory $adapters constructor param:

    <type name="FrontCommerce\Integration\Model\HeadlessPayments\AdapterFactory">
      <arguments>
        <argument name="adapters" xsi:type="array">
          <item name="paypal_express" xsi:type="string">FrontCommerce\Integration\Model\HeadlessPayments\Adapter\PaypalExpress</item>
          <item name="payzen_standard" xsi:type="string">FrontCommerce\Integration\Model\HeadlessPayments\Adapter\PayzenStandard</item>
          <item name="ops_cc" xsi:type="string">FrontCommerce\Integration\Model\HeadlessPayments\Adapter\OpsCc</item>
          <item name="adyen_hpp" xsi:type="string">FrontCommerce\Integration\Model\HeadlessPayments\Adapter\AdyenHpp</item>
        </argument>
      </arguments>
    </type>

Document steps before deploying your first Front-Commerce application

Before going to production, you always have to ensure that some things are in place. They are less critical to your application, but still a big part of any Front-Commerce application.

We should document:

  • robots.txt
  • theme colors (template/index.html, template/error.html, app-shell.html)
  • static pages
    • theme/pages/Maintenance
    • theme/pages/Offiline
    • theme/pages/ServerError
    • themes/pages/NotFound)
  • sitemap
  • favicon
  • manifest
  • template/app-shell.html
  • analytics
    • Google Analytics
      • npm install --save github:front-commerce/analytics.js-integration-google-analytics
      • Add integration in src/config/analytics.js
        {
                name: "google-analytics",
                needConsent: true,
                settings: {
                  "Google Analytics": {
                    trackingId: "XXXXX",
                    enhancedEcommerce: true
                  }
                },
                script: () =>
                  require("@segment/analytics.js-integration-google-analytics")
        }
        
      • Activate Enhanced Ecommerce in Google Analytics in Admin > View > E-Commerce parameters. And add steps in checkout labelling:
        1 Addresses
        2 Shipping
        3 Payment
  • config/website.js::default_image_path
  • public/images/resized/placeholder.png
  • public/images/resized/error.png
  • Ensure that all texts and links in the footer are valid
  • ...

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm react-infima Unavailable

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • fix(deps): update dependency infima to v0.2.0-alpha.43
  • fix(deps): update docusaurus monorepo to v2.4.3 (@docusaurus/core, @docusaurus/module-type-aliases, @docusaurus/plugin-client-redirects, @docusaurus/plugin-content-blog, @docusaurus/plugin-google-gtag, @docusaurus/plugin-ideal-image, @docusaurus/preset-classic)
  • chore(deps): update dependency pretty-quick to v3.3.1
  • fix(deps): update dependency @algolia/client-search to v4.23.3
  • fix(deps): update dependency @giscus/react to v2.4.0
  • fix(deps): update dependency dotenv to v16.4.5
  • fix(deps): update dependency react-slick to v0.30.2 (react-slick, @types/react-slick)
  • chore(deps): update dependency @tsconfig/docusaurus to v2
  • chore(deps): update dependency husky to v9
  • chore(deps): update dependency node to v20
  • chore(deps): update dependency prettier to v3
  • chore(deps): update dependency pretty-quick to v4
  • chore(deps): update dependency typescript to v5
  • chore(deps): update pnpm to v9
  • fix(deps): update dependency @giscus/react to v3
  • fix(deps): update dependency @mdx-js/react to v3
  • fix(deps): update dependency clsx to v2
  • fix(deps): update dependency prism-react-renderer to v2
  • fix(deps): update dependency react-use-intercom to v5
  • fix(deps): update docusaurus monorepo to v3 (major) (@docusaurus/core, @docusaurus/module-type-aliases, @docusaurus/plugin-client-redirects, @docusaurus/plugin-content-blog, @docusaurus/plugin-google-gtag, @docusaurus/plugin-ideal-image, @docusaurus/preset-classic)
  • 🔐 Create all rate-limited PRs at once 🔐

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

npm
package.json
  • @algolia/client-search 4.14.3
  • @docusaurus/core 2.4.1
  • @docusaurus/plugin-client-redirects 2.4.1
  • @docusaurus/plugin-content-blog 2.4.1
  • @docusaurus/plugin-google-gtag 2.4.1
  • @docusaurus/plugin-ideal-image 2.4.1
  • @docusaurus/preset-classic 2.4.1
  • @giscus/react ^2.2.8
  • @heroicons/react 2.0.13
  • @mdx-js/react 1.6.22
  • autoprefixer 10.4.13
  • clsx 1.2.1
  • dotenv 16.0.3
  • infima 0.2.0-alpha.42
  • postcss 8.4.21
  • prism-react-renderer 1.3.5
  • react 18.2.0
  • react-dom 18.2.0
  • react-hubspot-form 1.3.7
  • react-infima 0.0.1-alpha.4
  • react-player 2.11.0
  • react-slick 0.29.0
  • react-twitter-embed 4.0.4
  • react-use-intercom 2.0.0
  • tailwindcss 3.2.4
  • @docusaurus/module-type-aliases 2.4.1
  • @tsconfig/docusaurus 1.0.7
  • @types/react 18.0.27
  • @types/react-slick 0.23.10
  • husky 8.0.3
  • prettier 2.8.1
  • pretty-quick 3.1.3
  • typescript 4.9.4
  • node >=18.16
  • pnpm >=8.6
  • pnpm 8.6.0
nvm
.nvmrc
  • node 18

  • Check this box to trigger a request for Renovate to run again on this repository

Lower the typo error tolerance

Hi,

IMO the typo error tolerance is a little too high for the search results to be relevant.

For instance, if I want to search some documentation related to the customers:

I would rather like to see no result at all than these.

Document dataloaders and data invalidation 

Gather documentation from our old tools, and update this issue with relevant documentation information before adding them to official developers documentation.

Goal : improve performance for custom loaders (ex: fetch a new endpoint from magento)


Notes/Draft:

Dataloaders and cache invalidation

Why?

One of the main responsibility of GraphQL modules in Front-Commerce is fetching data from remote sources in resolvers.

A naive approach may reach a few limits in a real application. For instance, lets say one has a resolver on a Product.qty field that fetch the current quantity in stock from https://inventory.example.com/stock/PRODUCT_SKU and a query like below:

{
  category("pants") {
    products({ limit: 10 }) {
      sku
      name
      qty
    }
  }
}

The problem is that this query would lead to many HTTP requests from the server to the remote datasource:

  • 1 request to fetch category and its products, with sku and name (in the best case)
  • 10 additional requests to fetch products qty field

The qty requests will be started only after the previous category response has been received, leading to waterfalls.

This problem is also known as the N+1 problem and Dataloaders are a way to solve this using batching and caching.

What are Dataloaders?

Dataloader is a pattern promoted by Facebook, from their internal implementations, to solve problems with data fetching. We use this name because it is the name of the reference implementation in Javascript: facebook/dataloader.

A dataloader is instantiated with a batching function, that will allow to fetch data in a grouped way. It also has a caching strategy that prevents fetching the same data twice in the same request (by default) or as soon as it is available in the cache (if using a Redis cache for instance).

In our previous example, if the Product.qty resolver was implemented using a dataloader the query could have been resolved using only 2 remote API requests:

We encourage you to read the dataloader readme documentation to know more about how it works.

Front-Commerce only provides a small factory function to create Dataloaders from your GraphQL modules while keeping caching stategies configurable. Under the hood it is a pure dataloader instance that is made available to you.

Using Dataloaders in Front-Commerce

When building a GraphQL module, Front-Commerce will inject a makeDataloader factory function in your module’s contextEnhancer function.

The makeDataloader factory allows developers to build a dataloader without worrying about the current store scope (in a multistore environment) or caching stategies.

Here is an example based on the use case above:

// GraphQL module definition file
// For this example the code is in the same file, but it is recommended to extract
// code in different ones
const { reorderForIds } = require("../common/dataloaderHelpers");

const StockLoader = (makeDataLoader, axiosInstance) => {
  // our batching function that will be injected in the dataloader factory
  // it is important to return results in the same order than the passed `skus`
  // hence the use of `reorderForIds` (documented later in this page)
  const loadStocksBatch = skus => {
     return axiosInstance
        .get("/batch/stock", { params: { skus })
        .then(response => response.data.items)
        .then(reorderForIds(skus, "sku"));
  }

  // The `Stock` key here must be unique across the project
  // and is used in cache configuration to determine the caching strategy to use
  const loader = makeDataLoader("Stock")(
    skus => loadStocksBatch(skus)
  );

  return {
    loadBySku: sku => loader.load(sku)
  }
};

const typeDefs = `extend type Product {
  qty: Int
}`;

const resolvers = {
  Product: {
    qty: ({ sku }, _, { loaders }) => {
      // use the loader instance to fetch data
      // batching and caching is transparent in the resolver
      return loaders.Stock.loadBySku(sku);
    }
  }
}

module.exports = {
  namespace: "Acme/Inventory",
  typeDefs,
  resolvers,
  contextEnhancer: ({ makeDataLoader, config }) => {
    const axiosInstance = axios.create({
      baseURL: config.inventoryApiEndpointUrl
    });
    return {
      // create an instance of the loader, to be made available in resolvers
      Stock: StockLoader(makeDataLoader, axiosInstance)
    };
  }
};

Helpers available to build dataloaders

Writing batching functions and loaders could lead to reusing the same patterns. We have extracted some utility functions to help you in this task.

One can find them in the src/server/model/common/dataloaderHelpers.js module.

reorderForIds

Batch functions must satisfy two constraints to be used in a dataloader (from the facebook/dataloader documentation):

  • The Array of values must be the same length as the Array of keys.
  • Each index in the Array of values must correspond to the same index in the Array of keys.

This is what the reorderForIds is aimed at helping with.
Signature: const reorderForIds = (ids, idKey = "id") => data => sortedData;

It will sort data by idKey to match the order from the ids array passed in parameters. In case no matching values is found, it will return null and log a message so you could then understand why no result was found for a given id.

Example usage:

    return Observable.fromPromise(
      axiosInstance.get("/frontcommerce/price", { params })
    )
      .map(response => response.data)
      .map(reorderForIds(skus, "sku"));

reorderForIdsCaseInsensitive

As its name implies, it is the same than reorderForIds but ids are compared in a case insensitive way.

Example:

    return axiosInstance
      .get(`/products`, { params: searchCriteria })
      .then(response => response.data.items.map(convertMagentoProductForFront))
      .then(reorderForIdsCaseInsensitive(skus, "sku"));

reorderUrlsForIds

Example:

    const removeLeadingSlash = url => url.replace(/^\//, "");
    return axiosInstance
      .get("/frontcommerce/urls/match", { params })
      .then(response => response.data)
      .then(reorderUrlsForIds(urls.map(removeLeadingSlash), "url"));

makeBatchLoaderFromSingleFetch

Until now, we created batching functions using a remote API that allowed to request several results at once.

When using 3rd party APIs or legacy systems, such APIs are not available. Using dataloaders in this case will not allow you to reduce the number of requests in the absolute however it could still allow you to prevent most of these requests (or reduce its number in practice) thanks to caching. It is very convenient when dealing with a slow service.

The makeBatchLoaderFromSingleFetch allows you to create a batching function from a single fetching function very easily.

Pseudo signature: makeBatchLoaderFromSingleFetch = ( function singleFetch, function singleResponseMapper = ({ data }) => data ) => ids => sortedData;

Example:

// src/server/model/catalog/products/loaders/product_option.js
const {
  makeBatchLoaderFromSingleFetch
} = require("../../../common/dataloaderHelpers");

// ...
const loadOptionsBatch = makeBatchLoaderFromSingleFetch(
  sku =>
    axiosInstance.get(
      `/configurable-products/${encodeURIComponent(sku)}/options/all`
    ),
  response => response.data.map(convertProductOptionForFront)
);

// ...
const optionsLoader = makeDataLoader("CatalogProductOption")(skus =>
  loadOptionsBatch(skus).toPromise()
);

Caching dataloaders data

By default, all dataloaders are using a per-request in-memory caching strategy. It means that during the same GraphQL query, the same data will only be requested once.

Front-Commerce is also shipped with a persistent cache implementation, using a redis stategy. One can implement new strategies to support more services (we also can help and support more strategies, contact us).

The dataloader cache must be configured in the src/config/caching.js configuration file. If the configuration is empty (an empty object) only per-request cache will be used. Here is how one can configure persistent cache:

module.exports = {
  redis: {
    caches: "*", // or ["LoaderKeyA", "LoaderKeyB"]
    disabled: ["CatalogPrice"],
    config: {
      host: "redis"
    }
  }
};
  • configuration main keys (in this example redis) are the name of the strategy to enable
  • each strategy has the following configuration:
    • caches: keys of the loader to cache ("*" for all). The key is the first argument passed to the makeDataLoader factory
    • disabled: a blacklist of loaders to not cache (convenient if caches is "*")
    • config: a strategy specific configuration (depends on the strategy implementation)

Invalidating the cache

For persistent cache, it is necessary that remote systems invalidate cache when relevant.

Front-Commerce provides several endpoints for it. They respond to GET queries and are secured with a token to be passed in a auth-token header.
The expected token must be configured in src/config/servicesKeys/cache.js.

  • /_cache: invalidate all data in persistent cache
  • /_cache/:scope: invalidate all data for a given scope (for instance one store)
  • /_cache/:scope/:key: invalidate all data of a given loader (matching :key) for a given store
  • /_cache/:scope/:key/:id: invalidate cached data for a single id of a given loader in a given store

Note: our Magento2 extension handles cache invalidation by default

Current dataloaders

Here is a list (as of v0.15) of Front-Commerce dataloader keys:

  • CatalogCategory
  • CatalogCategoryProduct
  • CatalogPrice
  • CatalogProduct
  • CatalogProductAttribute
  • CatalogProductAttributeCode
  • CatalogProductChildren
  • CatalogProductCrossells
  • CatalogProductCustomOption
  • CatalogProductMedia
  • CatalogProductOption
  • CatalogProductRelated
  • CatalogProductStock
  • CatalogProductUpsells
  • categoryUrl
  • CmsBlock
  • CmsPage
  • Countries
  • Navigation
  • Post
  • PostsList
  • productUrl
  • Swatch
  • UrlMatcher

Document how to handle 4XX or 5XX error codes in GraphQL loaders

WIP documentation for withDefault404Result

4XX or 5XX HTTP error codes are throwing errors when using axios. But this is not always the wanted behavior in a GraphQL schema. This is especially true for 404 errors that shouldn't throw but return null in a GraphQL resolver.

One can use withDefault404Result(promise, defaultResult) from node_modules/front-commerce/src/server/core/graphql/queryResponseBuilders.js to handle such case.

For instance, if you want to fetch a product but return null, you could do :

const {
  withDefault404Result
} = require("server/core/graphql/queryResponseBuilders");

const loadProduct = withDefault404Result(
  fetch(`/product/${sku}`).then(response => response.data),
  null
);

Document the Magento2 storefront redirection

From our legacy documentation:

Front-End

Introduction

Front-Commerce's Magento module comes with a default system
to disable stock front-end. It restricts access to front-end
URLs while keeping the back-end available. It offers a few
configuration options to permit some routes to stay
available.

Temporarily disable the restriction

By default, every request to the front-end will be
redirected to FC's root.

You can disable the "firewall" by choosing "No" from the
administration panel > General > FrontCommerce > Disable
Magento Front-End.

Granular configuration

Three behaviors are available :

  • Accept the requested route and let Magento handle it
    casually (useful for payment modules).
  • Forward the requested route to FC : the redirection will
    have the same path but will use FC's base URL instead of
    Magento's.
  • Manually choose the target route.

If none of these rules matched, the request will be
redirected to FC's root.

The matching system use regexes that will be computed
against the request's URI.

They are configurable via the standard Dependency Injection
System.

Here is an example configuration :

<type name="FrontCommerce\Integration\Observer\DisableFrontEnd">
    <arguments>
        <argument name="routingPolicies" xsi:type="array">
            <item name="/accept/" xsi:type="const">FrontCommerce\Integration\Observer\DisableFrontEnd::ROUTING_POLICY_ACCEPT</item>
            <item name="/forward/" xsi:type="const">FrontCommerce\Integration\Observer\DisableFrontEnd::ROUTING_POLICY_FORWARD</item>
            <item name="/account/" xsi:type="string">user</item>
        </argument>
    </arguments>
</type>

Every request matching /accept/ will be handled by
Magento (use-case n°1).

Every request matching /forward/ will be forwarded to FC
(use-case n°2).

Every request matching /account/ will be redirected to
<fc-url>/user (use-case n°3).

Remaining requests will be redirected to FC root.

Doc revamp to allow new content architecture

Time has come to publish our official documentation publicly 🎉.

This issue is about rearchitecting content so information remains easy to find within the mass of information. Please do not hesitate to share your advices or ressources for inspiration.

It may require changing our doc tool, since Docusaurus is mostly targeting documentation for libraries. But it must remains: simple, published as a static site, markdown based, allow for a HP and blog posts management.

Here are some documentations and resources for inspiration:

Note: automated API documentation (ESDoc, JSDoc or another format), GraphQL schema and event Pacts documentation will be generated and published (maybe publicly) later, so the the new content architecture must take this into account

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.