Application plugins
ScandiPWA introduces the concept of "plugins". This is a feature of ScandiPWA extensions.
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 type of class proxy you would like to implement. If is is:
member-function,member-properties,static-memberit requires an additional configuration object with method or a property name mapped to the proxy implementation.classit expects the proxy implementation without any configuration objects.
Create a new plugin file following these guidelines.
In this file,
export defaultthe plugin options: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 at the reference 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.
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
CartQuerydeclared inCart.query.jsis bind to a namespaceQuery/Cart.We plan on modifying the class method, therefore we use
member-functionproxy type. It is special and requires a configuration object. It requires a method name as a key.Create a new file
CartQuery.plugin.jsinsrc/plugin, pay attention topluginpost-fix.Define an
export defaultobject: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
_getCartTotalsFieldstherefore we declare it in themember-functionconfiguration object.
Proxy implementation function of
member-functiontype takes following arguments:args,callbackandinstance. We do not need to call any other methods of theCartQueryclass 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_totalandbase_currency_code.
const addBaseFields = (args, callback) => {
return [
...callback(...args),
'base_grand_total',
'base_currency_code'
];
};
export default {
'Query/Cart': {
'member-function': {
_getCartTotalsFields: addBaseFields
}
}
};To create a plugin for a function
Understand which function you would like to proxy. Retrieve this function namespace by looking at it's leading comments.
Define the type of class proxy you would like to implement. In this case it is
function.Create a new plugin file following this guidelines.
In this file,
export defaultthe plugin options:Use namespace you obtained at the step 1).
Use the plugin type you defined at the step 2).
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.
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
getInitialStatedeclared inConfig.reducer.jsis bind to a namespaceStore/Config/Reducer/getInitialState.We plan on modifying the function assignment, therefore we use
functionproxy type.Create a new file
ConfigStore.plugin.jsinsrc/plugin, pay attention to plugin post-fix.Define an
export defaultobject:Use our namespace key from the step 1) -
Store/Config/Reducer/getInitialState.Use the plugin type from step 2) -
function.
Proxy implementation function of
functiontype takes following arguments:args,callbackandcontext. 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 filedgtm.
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:
/* @namespace Component/AddToCart/Container */
export class AddToCartContainer extends PureComponent {
// ...
}You are now able to proxy these object types:
class methods -
member-functionclass properties -
member-propertiesstatic methods of a class -
static-memberclass 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.
Proxy implementation syntax
The proxyImplmentations used in the example can be:
A function implementing a proxy
An object with
positionandimplementationkeys, where:positionis a numerical position of a plugin (default is100)implementationis 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
}The class property proxy implementation function takes:
Member - an original value of the class property
Instance - the original class instance
An example of such function is:
(member, instance) => {
// TODO: implement
}The static class method proxy implementation function takes:
An array of arguments from the caller
Callback - an original method
An example of such function is:
(args, callback) => {
// TODO: implement
}The class proxy implementation function takes:
Class - a class you intend to modify (not an instance!)
An example of such function is:
(Class) => {
// TODO: implement
}The function proxy implementation function takes:
An array of arguments from the caller
Callback - an original method
Context - the original context of a function
An example of such function is:
(args, callback, context) => {
// TODO: implement
}Last updated
Was this helpful?