Application plugins

ScandiPWA introduces the concept of "plugins". This is a feature of ScandiPWA extensions.

To create a plugin - means to create a programmable proxy between original function and the function caller. Plugin can modify original function arguments and return value.

To create a plugin for class

  1. Understand which class member you would like to proxy. Retrieve this class namespace by looking at it's leading comments.

  2. Define the type of class proxy you would like to implement. If is is:

    • member-function, member-properties, static-member it requires an additional configuration object with method or a property name mapped to the proxy implementation.

    • class it expects the proxy implementation without any configuration objects.

  3. Create a new plugin file following these guidelines.

  4. In this file, export default the plugin options:

    1. Use namespace you obtained at the step 1).

    2. Use the plugin type you defined at the step 2).

    3. Pay attention to configuration option of your desired plugin type.

  5. Take a look at the reference and define a proxy implementation based on your proxy type. Make sure you are passing in the correct arguments.

  6. Implement the proxy function according to your intention.

You can create class members that do not exist in the original classes. It is useful when you need some life-cycle member functions that are not present in the original class.

Remember to call thecallback even if the original member is not present, that will make your plugin compatible with other plugins around the same member, by calling them after your plugin finishes its work.

To create a plugin for a function

  1. Understand which function you would like to proxy. Retrieve this function namespace by looking at it's leading comments.

  2. Define the type of class proxy you would like to implement. In this case it is function.

  3. Create a new plugin file following this guidelines.

  4. In this file, export default the plugin options:

    1. Use namespace you obtained at the step 1).

    2. Use the plugin type you defined at the step 2).

  5. Take a look at the reference and define a proxy implementation based on your proxy type. Make sure you are passing in the correct arguments.

  6. Implement the proxy function according to your intention.

Pluggable objects

Plugins allow you to proxy any function or class of the application, which is bind to a namespace. To bind a an object to a namespace, it should have a leading comment starting with @namespace. Upon bind to a namespace one or multiple proxy types will become available.

Class declaration binding

To bind a class to a namespace, add leading comment to a class. Like this:

/* @namespace Component/AddToCart/Container */
export class AddToCartContainer extends PureComponent {
    // ...
}

You are now able to proxy these object types:

  • class methods - member-function

  • class properties - member-properties

  • static methods of a class - static-member

  • class instance itself - class

Heads Up!

If you want to plug into a class member that is an arrow function, still use member-function, not member-property

Function declaration & assignment binding

To bind a function declaration to a namespace add leading comment to it. Like this:

/* @namespace Util/Validation/validateHandler */
function validateHandler(/** ... */) {
    // ...
}

To bind functions assignment to a namespace:

/** @namespace Component/AddToCart/Container/mapStateToProps */
export const mapStateToProps = (state) => ({
    // ...
});

You can also do it for arrow functions passed as an argument:

fetch(/** ... */).then(
    /** @namespace Component/Braintree/Component/fetchThen */
    () => { /** ... */ } 
);

You are now able to proxy these object types:

  • function - function

File structure

The application plugin declarations must be located inside of your extension's folder src/plugin. To declare a plugin inside of this folder, you must name it with a plugin post-fix. For example: CartQuery.plugin.js.

Plugin configuration syntax

For a plugin to work, it should export default an object of configuration. The configuration object is structured the following way:

  • object keys are the namespaces you intend to apply proxy to

  • object values are objects, which define the type of proxy to apply

For example:

export default {
    'Framework/Component/App/Component': {
        'class': proxyImplmentations,
        'member-property': {
            contextProviders: proxyImplmentations
        }
    }
};

In this case, the object has only one key - Framework/Component/App/Component which references an object bind to this namespace. We know this object is a class declaration, therefore we are now allowed to use the class-declaration proxy types. We utilize class and member-property types.

The proxy typesmember-function, member-properties, static-memberrequire additional configuration object. This object is structured as follows:

  • object keys are the method or property names you want to provide a proxy for

  • object values are proxy function implementations

Other proxy types can be assigned to a proxy function implementation directly.

Proxy implementation syntax

The proxyImplmentations used in the example can be:

  • A function implementing a proxy

  • An object with position and implementation keys, where:

    • position is a numerical position of a plugin (default is 100)

    • implementation is a function implementing a proxy

You can also provide an array of above types.

Proxy function implementation types

Each proxy type expects a function with a different set of arguments. Here is an overview of function implementations for each proxy type:

The class method proxy implementation function takes:

  • An array of arguments from the caller

  • Callback - an original method

  • Instance - the original class instance

An example of such function is:

(args, callback, instance) => {
    // TODO: implement
}

Last updated