/
Project Context

Project Context

The Project Context module is a key part of the Customer Success module framework which establishes a container for project dependencies and a system for other modules to await certain dependencies before completing their own initialization process.

 

The Project Context Object

When included in a project, the Project Context module will establish an object in the global context at projects.<The Orbita project ID>:

The project context object is established with the following properties and methods:

The object is actually a proxy that prevents overwriting the base properties and assists with notifying subscribers awaiting dependencies when those dependencies have been initialized.

_revision

The experience designer flow revision ID at the time the project context was created, used to determine staleness.

isStale (hidden, established by proxy)

isStale will be true if the context is considered stale (determined by comparing the context revision ID to the current experience designer revision ID), false otherwise.

id

The ID of the Orbita project that the context belongs to.

host

The current Orbita environment host.

environmentName

The current Orbita environment name (the first segment of the host).

version

The version of Orbita that the environment is running on.

tier

The assumed tier (“dev”, “stage”, or “prod”) based on the presence of the word “sandbox” or a suffix of “-dev” or “-stage” in the host.

awaitDependencies

Parameters:

  • dependencies (string or array of strings): One or more keys of dependencies to await

Returns: A promise that resolves when all awaited dependencies have been initialized.

Getting the Project Context

Modules and other project code dependent on the project context should obtain it upon initialization using the following code:

const orbitaUtil = global.get("orbitaUtil"); const projectId = orbitaUtil.getProjectId(node); const establishDeferral = () => { let deferred = null; const promise = new Promise((resolve, reject) => { deferred = { resolve, reject }; }); promise.deferred = deferred; return promise; }; let projects = global.get("projects"); if (!projects) { projects = {}; global.set("projects", projects); } flow.set("project", undefined); let project = projects[projectId]; if (!project || project.isStale) { project = establishDeferral(); projects[projectId] = project; } Promise.resolve(project).then((resolvedProject) => { flow.set("project", resolvedProject); // For ease of access node.send(msg); // Not required if no subsequent code dependent on the context });

The code above does the following:

  • Check if the projects object exists in the global context

    • If not, create it

  • Clear any current reference to the project context in the flow context

  • Check for an existing project context that is not stale

    • If none is available, create a deferred promise as a placeholder for a new project context

  • Await the project context (this will execute immediately if there is an existing project that is not stale). Once it is available:

    • Set a new reference to the project context in the flow context (for ease of access)

    • Invoke any subsequent nodes

In the Project Context module, there is corresponding code:

let projects = global.get("projects"); if (!projects) { projects = {}; global.set("projects", projects); } const projectId = orbitaUtil.getProjectId(node); let existing = projects[projectId]; if (existing && existing.deferred) { const deferral = existing.deferred; const newContext = createContext(projectId); projects[projectId] = newContext; deferral.resolve(newContext); } else if (!existing || existing.isStale) { projects[projectId] = createContext(projectId); }

This code does the following:

  • Check if the projects object exists in the global context

    • If not, create it

  • Check for a deferred promise placeholder

    • If one exists, create a new project context, replace the placeholder with it, and resolve the deferred promise

    • If there is no placeholder, and there is either no existing context, or the existing context is stale, create a new project context

Awaiting Dependencies

After getting the project context, dependencies can be awaited with code such as:

const project = flow.get("project"); project.awaitDependencies(["settings", "utilities", "errorHandling"]).then((resolvedDependencies) => { node.send(msg); }).catch((error) => { node.error(`<MODULE NAME>: Dependency resolution failed: ${error}`); });

This code does the following:

  • Get the project context from the reference in the flow context.

  • Call awaitDependencies, passing it the names of any dependencies required

  • Once those dependencies are available, the promise returned by awaitDependencies will be resolved with an object containing references to all resolved dependencies (references will also be added to the project context object).

  • Invoke any subsequent nodes (which presumably contain code dependent on the awaited dependencies)

Initializing Dependencies

Dependencies are initialized simply by setting a property with the module key on the project context object:

When initializing a new module, it’s a best practice to freeze the module object to avoid any unexpected modifications.

When awaitDependencies is called, if the dependency does not already exist, a deferred promise is established as a placeholder (similar to the process when the project context itself is initialized). Whenever a property is set on the project context object, a check is done for any such placeholders, which are resolved at that time.

Related content

Content Sync
Content Sync
More like this
Orbita New UI
Orbita New UI
More like this
Error Handling
Error Handling
More like this