ScandiPWA introduces the concept of "plugins". This is a feature of .
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
Understand which class member you would like to proxy. Retrieve this class namespace by looking at it's leading comments.
Define the 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.
Create a new plugin file following .
In this file, export default the:
Use namespace you obtained at the step 1).
Use the plugin type you defined at the step 2).
Pay attention to configuration option of your desired plugin type.
Take a look and define a proxy implementation based on your proxy type. Make sure you are passing in the correct arguments.
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.
The main purpose of this plugin is to inject additional fields base_grand_total and base_currency_code into the Cart.query.js file's class method _getCartTotalsFields return value.
The class CartQuery declared in Cart.query.js is bind to a namespace Query/Cart.
We plan on modifying the class method, therefore we use member-function proxy type. It is special and requires a configuration object. It requires a method name as a key.
Create a new file CartQuery.plugin.js in src/plugin, pay attention to plugin post-fix.
Define an export default object:
Use our namespace key from the step 1) - Query/Cart.
Use the plugin type from step 2) - member-function.
As stated in 2) the method we intend to modify is _getCartTotalsFields therefore we declare it in the member-function configuration object.
Proxy implementation function of member-function type takes following arguments: args, callback and instance. We do not need to call any other methods of the CartQuery class instance, therefore, we can omit the last argument.
Call the original method passing in the original arguments to get the original return value. This is done by calling callback(...args). Then, we extend the original return value with two additional fields: base_grand_total and base_currency_code.
Understand which function you would like to proxy. Retrieve this function namespace by looking at it's leading comments.
Use namespace you obtained at the step 1).
Use the plugin type you defined at the step 2).
Implement the proxy function according to your intention.
The main purpose of this plugin is to inject a new field gtm into the file's Config.reducer.js reducer ConfigReducer initial state. We know, that the function getInitialState is responsible for that.
The function getInitialState declared in Config.reducer.js is bind to a namespace Store/Config/Reducer/getInitialState.
We plan on modifying the function assignment, therefore we use function proxy type.
Create a new file ConfigStore.plugin.js in src/plugin, pay attention to plugin post-fix.
Define an export default object:
Use our namespace key from the step 1) - Store/Config/Reducer/getInitialState.
Use the plugin type from step 2) - function.
Proxy implementation function of function type takes following arguments: args, callback and context. We have no intention to interact with that function context, therefore, we can omit the last argument.
Call the original method passing in the original arguments to get the original return value. This is done by calling callback(...args). Then, we extend the original return value with one additional filed gtm.
import BrowserDatabase from 'Util/BrowserDatabase';
const addGtmToConfigReducerInitialState = (args, callback, instance) => {
// We need to make sure the field "gtm" is an object
const { gtm } = BrowserDatabase.getItem('config') || { gtm: {} };
return {
...callback(...args),
gtm
};
};
export default {
'Store/Config/Reducer/getInitialState': {
'function': addGtmToConfigReducerInitialState
}
};
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:
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
Define the you would like to implement. In this case it is function.
Create a new plugin file following .
In this file, export default the:
Take a look and define a proxy implementation based on your proxy type. Make sure you are passing in the correct arguments.
In this case, the object has only one key - Framework/Component/App/Component which references an object . We know this object is a class declaration, therefore we are now allowed to use the . We utilize class and member-property types.