Sign up to receive SuiteScript examples and advice directly in your email inbox.

SuiteScript Design - Alias Modules

Created: December 14, 2020

Last week we looked at mimicking the functionality of a REST endpoint with its own module (e.g. retrieving a User, or a list of Users, refreshing a token, etc).

For complex integrations that rely on a large set of resources from an external system, you might start to pile up a bunch of these modules, which will start to clutter your module dependency list.

Follow along with the code here.

Take, for example, a Map/Reduce script that needs to touch a whole bunch of the SMA endpoints to consolidate data in NetSuite:

define([
  '../api/sma_api_Application',
  '../api/sma_api_Assignments',
  '../api/sma_api_Payments',
  '../api/sma_api_Programs',
  '../api/sma_api_Task',
  '../api/sma_api_Token',
  '../api/sma_api_User',
  'N/https',
  'N/runtime',
  'N/search'
], (application, assignments, payments, programs, task, token, user, https, 
  runtime, search) => {
  // ...
})

The more endpoints a single module needs to leverage, the longer this list gets. To shorten the list and organize our dependency imports a little, we can use what I've been calling an "alias module". The idea is to use the alias module as a wrapper for the long list of closely related dependencies.

Since we know our Map/Reduce needs a ton of the API modules, let's make an API alias module specifically for use by the Map/Reduce (filename: sma_api.js):

/**
 * Convenience module for importing all API modules
 * @NApiVersion 2.1
 */
define([
  '../api/sma_api_Application',
  '../api/sma_api_Assignments',
  '../api/sma_api_Payments',
  '../api/sma_api_Programs',
  '../api/sma_api_Task',
  '../api/sma_api_Token',
  '../api/sma_api_User'
], (application, assignments, payments, programs, task, token, user) => ({
  application,
  assignments,
  payments,
  programs,
  task,
  token,
  user
}))

As you can see, there is no logic here, only a wrapper that imports a long list of modules just to re-export them. What do we gain by doing this?

Essentially, we have given our Map/Reduce the ability to import all of these dependencies as a single Object, effectively "grouping" the dependencies together:

define([
  './sma_api',
  'N/https',
  'N/runtime',
  'N/search'
], (api, https, runtime, search) => {
  // ...
  api.token.refresh()
  
  let userData = api.user.get(userId)
  let applications = api.application.list({ applicant: userId })
})

The dependency list gets vastly shorter, and the code even gets a little cleaner as it becomes very clear where our "User" data is coming from.

By the way, there's nothing here that's unique to integrations. You can use this same pattern to group any modules you wish, regardless of functionality.

HTH

-EG