Entity Class
Entities in Nymph work pretty much like regular objects, and this is due to the Entity class. The Entity class constructor returns a proxy to allow accessing data on it just like a regular object while keeping track of changes and only unserializing data from the DB when it's first accessed. Instance methods and properties begin with "$" to differentiate them from data.
In the client, assigning a property internally marks that property as
"dirty", and calling $patch
will push just the changed
properties up to the server, whereas $save
would push all properties.
Entities can be organized using tags. To add, remove, and check tags, the
methods $addTag
, $removeTag
, and
$hasTag
are used, respectively. Each takes any number of tags as
arguments.
const entity = await MyEntity.factory();
entity.$addTag('foo', 'bar');
entity.$hasTag('foo'); // True
entity.$removeTag('foo', 'bar');
entity.$hasTag('foo'); // False
Entities that have been saved inside another entity's property are loaded as
"sleeping references". This means their data is not actually pulled from the
database/server. It will "wake up" when you use $wake
on it or
$wakeAll
on the entity that contains it.
To clear the cache of referenced entities, so that the next time one is
awoken, it will be pulled from the database, use the $clearCache
method in Node.js or the $refresh
method in the client.
// Create some entities.
let entity = await MyEntity.factory();
entity.foo = await MyEntity.factory();
entity.foo.bar = 'Old value.';
await entity.foo.$save();
await entity.$save();
// Get a copy of the referenced entity.
let instOfFoo = await nymph.getEntity(
{ class: MyEntity },
{ type: '&', guid: entity.foo.guid }
);
// And change a value on it.
instOfFoo.bar = 'New value.';
await instOfFoo.$save();
console.log(entity.foo.bar); // Outputs 'Old value.'
// If on Node.js
entity.$clearCache();
await entity.foo.$wake();
// Else if on the client
await entity.$refresh();
await entity.foo.$wake();
// End if
console.log(entity.foo.bar); // Outputs 'New value.'
Much like clearing the entity cache, you may need to refresh the entity's
own data in Node.js. Use the $refresh
method, just like in the client,
for this.
// Create an entity.
const entity = await MyEntity.factory();
entity.foo = 'Old value.';
await entity.$save();
// Get a copy of the entity.
const instOfEnt = await nymph.getEntity(
{ class: MyEntity },
{ type: '&', guid: entity.guid }
);
// And change a value on it.
instOfEnt.foo = 'New value.';
await instOfEnt.$save();
console.log(entity.foo); // Outputs 'Old value.'
await entity.$refresh();
console.log(entity.foo); // Outputs 'New value.'
To save an entity, use the $save
method. Likewise, to delete
the entity, use the $delete
method. You can also call the
saveEntity
,
deleteEntity
, and deleteEntityByID
methods of
Nymph
. The Entity
class uses these methods.
const entity = await MyEntity.factory();
// Save the entity.
await entity.$save();
// or
await nymph.saveEntity(entity);
// or
await nymph.saveEntities([entity]);
// (Client only.) Save only the data that has changed.
await entity.$patch();
// or
await nymph.patchEntity(entity);
// or
await nymph.patchEntities([entity]);
// Delete the entity.
await entity.$delete();
// or
await nymph.deleteEntity(entity);
// or
await nymph.deleteEntities([entity]);
Entities can't be checked using the ==
operator. Instead, you can
use the following entity methods.
$is
- Perform a less strict comparison of two entities (basically a GUID check). To return true, the entities must meet the following criteria.- They must be entities.
- They must have equal GUIDs, or both can have no GUID.
- If they have no GUIDs, their data and tags must be equal.
$equals
- Perform a more strict comparison of two entities (basically a GUID + data + tags check). To return true, the entities must meet the following criteria. Unlike$is
, this method can't be used on sleeping references.- They must be entities.
- They must have equal GUIDs, or both can have no GUID.
- Their data and tags must be equal.
$inArray
- Check whether the entity is in an array. Takes two arguments, the array and a booleanstrict
. Ifstrict
is false or undefined, the function uses$is
to compare, and if it's true, the function uses$equals
.$arraySearch
- Search an array for the entity and return its index, or-1
if it's not found. Takes two arguments, the array and a booleanstrict
. Ifstrict
is false or undefined, the function uses$is
to compare, and if it's true, the function uses$equals
. This method may return 0, which evaluates to false, so you should use$inArray
if you are only checking whether the entity is in the array.
// Assuming the entity with GUID 'a4c1591d6ea91c8450d2d360' exists.
let entity = await MyEntity.factory('a4c1591d6ea91c8450d2d360');
let entity2 = await MyEntity.factory('a4c1591d6ea91c8450d2d360');
entity.$is(entity2); // True
entity.$equals(entity2); // True
entity2.someProp = 'some new value';
entity.$is(entity2); // True
entity.$equals(entity2); // False
const arr = [null, null, entity2];
entity.$arraySearch(arr); // 2
entity.$inArray(arr); // True
entity.$arraySearch(arr, true); // -1
entity.$inArray(arr, true); // false
Client side Nymph entities can use the $serverCall
method to
call methods on a server side instance of the entity.
$serverCall
expects three parameters.
method
- the name of the method to call on the server side object.params
- an array of the parameters to pass to the method.stateless
- if set to true, the method won't update the entity with the returned server side representation.
Normally, when you use this method, just before the promise is fulfilled,
the entity's data will be replaced with that of the entity on the server
side after the method was run. This will cause any awoken entities in the
data of your entity to be replaced with sleeping entities, so you will have
to run $readyAll
again. If you know that the server side method
will not change any of the data on the entity, you can set
stateless
to true.
You can also call static methods on the server with serverCallStatic
.
In order to be called from the client side, the method must be listed in the
$clientEnabledMethods
or
clientEnabledStaticMethods
property in the Node.js class. This
guards against a user submitting tailored requests to perform potentially
dangerous tasks on the server side. If the method is not listed, the request
will fail with a 403 Forbidden
status.
// You can use $serverCall and serverCallStatic directly.
try {
const success: boolean = await todo.$serverCall('$archive', []);
if (!success) {
alert("Couldn't archive " + todo.name);
}
} catch (e) {
alert('Error: ' + e.textStatus + "
Couldn't archive " + todo.name);
}
// Or you can define methods like this in your client class.
class Todo extends Entity<TodoData> {
// ...
static async archiveAllDone(onlyOlderThanDay: boolean): Promise<boolean> {
return await this.serverCallStatic('archiveAllDone', [onlyOlderThanDay]);
}
async $archive(): Promise<boolean> {
return await this.$serverCall('archive', []);
}
}
// You'd use them like this.
const success = await Todo.archiveAllDone(true);
// And
const todo = await Todo.factory(someGuid);
const success = await todo.$archive();