While the BaseEngine class is a singleton, normally, it is possible to have multiple instances of the class in an application if the class is used in multiple contexts that have different providers.
Returns a COPY of the metadata configs array for the engine. This is a copy so you can't modify the original configs by modifying this array.
Returns a list of all core actions.
Returns the root category ID for core actions.
Observable that emits when any data property changes due to a refresh. Subscribe to this to react to engine data updates (e.g., sync Angular observables).
Events are emitted after data is refreshed in response to BaseEntity save/delete events. The event includes the full config and the new data array.
UserInfoEngine.Instance.DataChange$.subscribe(event => {
if (event.config.PropertyName === 'UserApplications') {
// Sync local state with engine's updated data
this.refreshLocalAppList();
}
});
Protected EntityOverridable property to set the debounce time for entity events. Default is 1500 milliseconds (1.5 seconds). This debounce time is used when immediate array mutations cannot be applied (e.g., when Filter, OrderBy, or AdditionalLoading overrides are present) and a full view refresh is required.
Note: When immediate mutations ARE possible (no Filter, OrderBy, or AdditionalLoading override), updates happen synchronously without any debounce delay.
Returns true if the data has been loaded, false otherwise.
Returns the loading subject. You can call await Config() and after Config() comes back as true that means you're loaded. However you can also directly subscribe to this subject to get updates on the loading status.
Returns a list of all non-core actions.
Returns the metadata provider to use for the engine. If a provider is set via the Config method, that provider will be used, otherwise the default provider will be used.
Returns the RunView provider to use for the engine. This is the same underlying object as the
Static InstanceReturns the global instance of the class. This is a singleton class, so there is only one instance of it in the application. Do not directly create new instances of it, always use this method to get the instance.
Private Static ProviderAdds a dynamic metadata configuration at runtime.
The metadata configuration to add
Optional contextUser: UserInfoThe context user information
Protected AdditionalSubclasses can override this method to perform additional loading tasks
Optional contextUser: UserInfoProtected CheckThis method is called to configure the ActionEngine. It loads the metadata for the actions, filters, and result codes and caches them in the GlobalObjectStore. You must call this method before running any actions. If this method was previously run on the instance of the ActionEngine, it will return immediately without re-loading the metadata. If you want to force a reload of the metadata, you can pass true for the forceReload parameter.
Optional forceRefresh: booleanIf true, the metadata will be loaded from the database even if it was previously loaded.
Optional contextUser: UserInfoIf you are running the action on the server side you must pass this in, but it is not required in an environment where a user is authenticated directly, e.g. a browser or other client.
Optional provider: IMetadataProviderExtended configuration method with object-based options. This provides a more flexible API compared to Config() with positional parameters.
Internally calls Config() after setting up options that Load() can access.
Optional options: ConfigExOptionsConfiguration options object
Promise that resolves when configuration is complete
await MyEngine.Instance.ConfigEx({
forceRefresh: true,
contextUser: currentUser
});
Protected DebounceThis method handles the debouncing process, by default using the EntityEventDebounceTime property to set the debounce time. Debouncing is done on a per-entity basis, meaning that if the debounce time passes for a specific entity name, the event will be processed. This is done to prevent multiple events from being processed in quick succession for a single entity which would cause a lot of wasted processing.
Override this method if you want to change how debouncing time such as having variable debounce times per-entity, etc.
Protected EndReturns an action based on its name
Protected GetThe Global Object Store is a place to store global objects that need to be shared across the application. Depending on the execution environment, this could be the window object in a browser, or the global object in a node environment, or something else in other contexts. The key here is that in some cases static variables are not truly shared because it is possible that a given class might have copies of its code in multiple paths in a deployed application. This approach ensures that no matter how many code copies might exist, there is only one instance of the object in question by using the Global Object Store.
Protected HandleThis method handles the individual base entity event. For events that can use immediate array mutations (no Filter, OrderBy, or AdditionalLoading override), processing happens synchronously without debounce. For events that require full view refresh, debouncing is applied to batch rapid successive changes.
Override this method if you want to have a different handling for the filtering of events that are debounced or if you don't want to debounce at all you can do that in an override of this method.
Protected HandleSubclasses of BaseEngine can override this method to handle individual MJGlobal events. This is typically done to optimize the way refreshes are done when a BaseEntity is updated. If you are interested in only BaseEntity events, override the HandleIndividualBaseEntityEvent method instead as this method primarily serves to filter all the events we get from MJGlobal and only pass on BaseEntity events to HandleIndividualBaseEntityEvent.
Protected HandleHandles the result of a single view load.
All BaseEngine sub-classes get an implementation of IStartupSink so they can be set the auto start in their app container, if desired, simply by adding the
Optional contextUser: UserInfoOptional provider: IMetadataProvider-
decorator. The BaseEngine implementation of IStartupSink.HandleStartup is to simply call
Protected InternalUtility method that determines if a given Action Category ID is a child of the specified parent category ID.
The ID of the category to check.
The ID of the parent category to check against.
True if the categoryId is a child of the parentCategoryId, false otherwise.
Checks if the specified action is a core action by checking if its category is a child of the core actions root category.
The action entity to check.
True if the action is a core action, false otherwise.
Protected LoadThis method should be called by sub-classes to load up their specific metadata requirements. For more complex metadata loading or for post-processing of metadata loading done here, overide the AdditionalLoading method to add your logic.
Optional forceRefresh: booleanOptional contextUser: UserInfoProtected LoadLoads the specified metadata configurations.
The metadata configurations to load
The context user information
Protected LoadOverride to ensure all action metadata is loaded without MaxRows limits. Action Params can have many records (1000+), so we need to ignore the entity's UserViewMaxRows setting.
Protected LoadLoads a single metadata configuration.
The metadata configuration to load
The context user information
Protected LoadHandles the process of loading a single config of type 'dataset'.
Protected LoadHandles the process of loading a single config of type 'entity'.
Protected NotifyNotify listeners that a data property has changed. Called automatically by HandleSingleViewResult after data refresh and by applyImmediateMutation for array operations. Subclasses can also call this manually when modifying data arrays directly.
The configuration for the property that changed
The current data array
Optional changeType: "delete" | "refresh" | "add" | "update"The type of change: 'refresh', 'add', 'update', or 'delete'
Optional affectedEntity: BaseEntity<unknown>For add/update/delete, the entity that was affected
Protected ProcessThis method does the actual work of processing the entity event. It is not directly called from the event handler because we want to first debounce the events which also introduces a delay which is usually desirable so that our processing is typically outside of the scope of any transaction processing that would have originated the event.
This is the best method to override if you want to change the actual processing of an entity event but do NOT want to modify the debouncing behavior.
Protected RunThis method runs any filters for the action. Subclasses can override this method to provide custom filter logic.
Protected RunThis method runs a single filter. Subclasses can override this method to provide custom filter logic.
Protected SetInternal method to set the provider when an engine is loaded
Protected SetupThis method is responsible for registering for MJGlobal events and listening for BaseEntity events where those BaseEntity are related to the engine's configuration metadata. The idea is to auto-refresh the releated configs when the BaseEntity is updated.
Protected StartProtected StartProtected TryProtected UpgradeUtility method to upgrade an object to a BaseEnginePropertyConfig object.
Protected ValidateThis method handles input validation. Subclasses can override this method to provide custom input validation.
Protected applyApplies an immediate array mutation based on the entity event type. This is faster than running a full view refresh for simple add/update/delete operations.
The configuration for the property being mutated
The entity event containing the affected entity and event type
Protected canDetermines if an immediate array mutation can be used instead of running a full view refresh. Immediate mutations are only safe when:
The configuration to check
true if immediate mutation is safe, false if a full view refresh is needed
Protected findFinds an entity in the array by matching all primary key columns. Supports composite primary keys by comparing all PrimaryKey fields from EntityInfo.
The array of entities to search
The entity to find (using its primary key values)
The index of the matching entity, or -1 if not found
Protected hasProtected isChecks if the exact entity object reference is already in the config's data array. Used to skip unnecessary refreshes for UPDATE events where the object was mutated in place.
The configuration to check
The entity to look for
true if the exact object reference is already in the array
Protected isChecks if an entity is in the config's data array by object reference OR by primary key match. Used for DELETE events where we need to know if the entity still exists in the array. The object reference may still exist (entity.Delete() just marks it deleted), but if it was manually spliced out by engine code, we check by primary key as fallback.
The configuration to check
The entity to look for
true if the entity is in the array (by reference or by primary key)
Static GetThis method will check for the existence of an instance of this engine class that is tied to a specific provider. If one exists, it will return it, otherwise it will create a new instance
Protected Static getReturns the singleton instance of the class. If the instance does not exist, it is created and stored in the Global Object Store. If className is provided it will be used as part of the key in the Global Object Store, otherwise the actual class name will be used. NOTE: the class name used by default is the lowest level of the object hierarchy, so if you have a class that extends another class, the lowest level class name will be used.
Base class for executing actions. This class can be sub-classed if desired if you would like to modify the logic across ALL actions. To do so, sub-class this class and use the
Register Class
decorator from the @memberjunction/global package to register your sub-class with the ClassFactory. This will cause your sub-class to be used instead of this base class when the Metadata object insantiates the ActionEngine.