- Intro
- Class Api
- Functional Api
- Advanced
- Access Control
- Entity Lifecycle
- Schema Versioning
- Permissions
- OperationStack
- Metrics
- Queries & Filters
- Catalogs & Collections
- Composing Workflows
- Developers
- Legacy
Entity Lifecycle: Fetching and Hydration
This guide explains the process of fetching and hydrating an entity in hub.js, using the Project entity as an example. The same series of steps applies to any entity, regardless of its backing store (e.g., Portal, Events, Discussion APIs).
Overview
When you request an entity (such as a Project), hub.js performs a series of steps to transform raw data from the backing store into a fully hydrated, type-safe entity object. This ensures that all properties are mapped, computed, and migrated as needed for runtime use.
Step-by-Step Process
This process should be encapsulated within the fetch{Entity}
function. This guide is intended for developers who are creating and maintaining the entity functions themselves. Consumers of Hub.js should never need to know any of these details.
1. Fetch from Backing Store
Fetching can be done by either the entity's unique id
or its human-friendly slug
. Supporting both lookup methods is important for flexibility in APIs and user-facing URLs.
Once the raw model object is retrived, we then start the process of converting it into the Entity.
2. Property Mapping
The raw model is transformed into an entity object using the PropertyMapper
and a property map (see getBasePropertyMap
. This step copies properties from the raw model structure (e.g., item.title
, data.view
) to the entity (name
, view
, etc.), handling deep mappings and read-only properties.
const mapper = new PropertyMapper(getBasePropertyMap());
const entity = mapper.storeToEntity(model, {});
Each entity should define it's own property map. Item backed entities can leverage getBasePropertyMap
to ensure consistentcy, but they will also need to add additional properties unique to the entity.
It's important to note that the PropertyMapper
is bi-directional, and is also used when converting the Entity back into the raw model, prior to being sent to the backing store.
3. Computed Properties
After the simple property mapping, additional properties are set using the computeProps
function. This includes:
- Generating URLs (e.g.,
thumbnailUrl
) - Migrating schemas (e.g.,
catalog
viaupgradeCatalogSchema
) - Setting up features and computing links
- Applying any additional logic
Both the raw model, and the entity are passed into this function, allowing the function to have acces to all the relevant information.
const hydratedProject = computeProps(model, entity, requestOptions);
Each entity should implement it's own computeProps
function, stored in the /_internal
folder, and it should not be exported from Hub.js.
4. Result: Fully Hydrated Entity
The result is a fully hydrated entity object, ready for use in the application: hydratedProject as IHubProject
Updating an Entity
Entities are generally handled as simple objects (vs class instances) and thus can be manipulated as needed. Once the application decides to persist the entity, it should call the related update{Entity}
function, which should follow a specific process to ensure data integrity and business rules are enforced:
- Ensure Unique Slug: Before persisting, the function checks that the entity's
slug
is unique to prevent conflicts in URLs and lookups. - Apply Business Logic: Any required business rules or validations are applied to the entity. This may include permission checks, field validations, or custom logic specific to the Entity.
- Fetch Latest Model: The current version of the entity is fetched from the backing store to ensure updates are applied to the most recent data.
- Apply Local Changes: The local changes are merged into the fetched model using the
PropertyMapper
'sentityToStore
method. This ensures only the intended properties are updated and the model remains consistent.
const updatedModel = mapper.entityToStore(localEntity, fetchedModel);
- Persist to Backing Store: The updated model is sent to the backing store (e.g., Portal API) to save the changes.
- Hydrate and Return Entity: Once the backing store confirms the update, the returned model is converted back into a fully hydrated entity using the same mapping and compute steps as initial loading.
This flow ensures that updates are atomic, business rules are enforced, and the returned entity reflects the latest persisted state.
Applicability to Other Entities
This lifecycle applies to all hub.js entities (Sites, Initiatives, Teams, etc.), regardless of their backing store. The property map and compute phase are tailored for each entity type, but the overall flow remains consistent:
- Fetch raw model from store
- Map properties to entity via PropertyMapper
- Implement a
computeProps
function to set additional properties and apply migration - Return hydrated entity