-
Notifications
You must be signed in to change notification settings - Fork 2
Modeling
The data model is implemented using classes, each representing an element defined in the specification.
Let’s take a look at how we use this model to build the example entity from the Siren specification:
import { Action, EmbeddedEntity, EmbeddedLink, Entity, Field, Link } from '@siren-js/client';
const embeddedOrderedItemsLink = new EmbeddedLink();
embeddedOrderedItemsLink.class = ['items', 'collection'];
embeddedOrderedItemsLink.rel = ['http://x.io/rels/order-items'];
embeddedOrderedItemsLink.href = 'http://api.x.io/orders/42/items';
const customerLink = new Link();
customerLink.rel = ['self'];
customerLink.href = 'http://api.x.io/customers/pj123';
interface EmeddedCustomerProperties {
customerId: string;
name: string;
}
const embeddedCustomerEntity = new EmbeddedEntity<EmeddedCustomerProperties>();
embeddedCustomerEntity.class = ['info', 'customer'];
embeddedCustomerEntity.rel = ['http://x.io/rels/customer'];
embeddedCustomerEntity.properties = {
customerId: 'pj123',
name: 'Peter Joseph'
};
embeddedCustomerEntity.links = [customerLink];
const orderNumberField = new Field<string>();
orderNumberField.name = 'orderNumber';
orderNumberField.type = 'hidden';
orderNumberField.value = '42';
const productCodeField = new Field<string>();
productCodeField.name = 'productCode';
// Field's type defaults to 'text' 🎉
const quantityField = new Field<number>();
quantityField.name = 'quantity';
quantityField.type = 'number';
const addItemAction = new Action();
addItemAction.name = 'add-item';
addItemAction.title = 'Add Item';
addItemAction.method = 'POST';
addItemAction.href = 'http://api.x.io/orders/42/items';
addItemAction.fields = [orderNumberField, productCodeField, quantityField];
// Action's type defaults to 'application/x-www-form-urlencoded' 🎉
const selfLink = new Link();
selfLink.rel = ['self'];
selfLink.href = 'http://api.x.io/orders/42';
const previousLink = new Link();
selfLink.rel = ['previous'];
selfLink.href = 'http://api.x.io/orders/41';
const nextLink = new Link();
selfLink.rel = ['next'];
selfLink.href = 'http://api.x.io/orders/43';
interface OrderProperties {
orderNumber: number;
itemCount: number;
status: string;
}
const orderEntity = new Entity<OrderProperties>();
orderEntity.class = ['order'];
orderEntity.properties = {
orderNumber: 42,
itemCount: 3,
status: 'pending'
};
orderEntity.entities = [embeddedOrderedItemsLink, embeddedCustomerEntity];
orderEntity.actions = [addItemAction];
orderEntity.links = [selfLink, previousLink, nextLink];
Pretty ugly, right? Luckily clients don’t need to build entities this way. Instead they receive an entity from a server, which is where parsing comes into play. However, we will reference these objects throughout the wiki using the variable names above.
The Entity
and EmbeddedEntity
classes define a method for looking up one of its actions by name.
orderEntity.getAction('add-item');
//=> returns the addItemAction object
embeddedCustomerEntity.getAction('deactivate');
//=> returns undefined
Additionally, the Action class defines a similar method for looking up one of its fields by name.
addItemAction.getField('quantity');
//=> returns the quantityField object
addItemAction.getField('description');
//=> returns undefined
Each model class implements the SirenElement
interface, meaning any element can accept a SirenElementVisitor
. Check out Traversing for more details.