SuiteScript 2.1 Singleton Pattern

04/16/2021

The following snippet is a module loaded into the User Event script (SuiteScript2.UE.js)


/**
 * @NApiVersion 2.1
 */

define([
    'N/record'
], (
    record
) => {
    'use strict';

    return (() =>  {

        let instance;

        const init = (context, thisRec) => {
            //@method checkOperationType
            function checkOperationType () {
                return (['create', 'edit'].includes(context.type));
            }

            //@method doSomething
            function doSomething() {
                if (checkOperationType()) {
                    //add module logic here
                }
            }

            return {
                doSomething
            };
        };

        return {
            getInstance: (context, thisRec) => {
                if (!instance) {
                    instance = init(context, thisRec);
                }
                return instance;
            }
        }
    })();
});
Filename: DoSomething.module.js

The following is a standard User Event script where we have loaded the module define above and executed the doSomething function.


/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */

define(
[
    '/SuiteScripts/doSomething.module.js'
],
function (
    DoSomethingModule
) {

    'use strict';

    //@method beforeSubmit
    function beforeSubmit (context) {
        try {
            const thisRec = context.newRecord;

            const doSomethingModule = DoSomethingModule.getInstance(context, thisRec);
            doSomethingModule.doSomething();

        } catch (e) {
            log.error({title: 'ERROR', details: e});
        }
    }
    
    //@method afterSubmit
    function afterSubmit (context) {
        try {
            const thisRec = record.load({
                type: context.newRecord.type,
                id: context.newRecord.id,
                isDynamic: true
            });

            const doSomethingModule = DoSomethingModule.getInstance(context, thisRec);
            doSomethingModule.doSomething();

            const id = thisRec.save({
                ignoreMandatoryFields: true,
                enableSourcing: true
            });
        } catch (e) {
            log.error({title: 'ERROR', details: e});
        }
    }

    return {
        beforeSubmit,
        afterSubmit
    };
});
Filename: SuiteScript2.UE.js

This approach encapsulates the module to it's own purpose only and not mix with other script logic.

Key Benefits
  • Easily turn on/off a particular logic that is part of the module or able to turn the module on/off in its entirety.
  • Separate the logic of a specific custom requirement to a module on it's own. This approach prevent mixing logic between different custom script.
  • Single SuiteScript entry point trigger (as necessary). No need to spun multiple script record, this helps with the user event script performance.