3.7 KiB
Sharkitek Repositories
The Sharkitek Repositories extension is designed to add global repositories of models. It helps to deduplicate instances of the same objects (with the same identifier) in an application. It could be thought as a tiny local database.
It adds a model class extension and a special model type that tries to use (and save) the models from the corresponding repository on deserialization.
Documentation
To link models to repositories, you can use the WithRepository
Sharkitek extension.
class Author extends WithRepository("Author")(Model)
{
@Property(SString)
name: string = undefined;
@Property(SString)
firstName: string = undefined;
@Property(SString)
@Identifier
email: string = undefined;
}
The only argument of WithRepository
is the name of the repository to use. The easier way to use Sharkitek Repositories is
to always use class name as repository name.
WithRepository
declares 3 methods in the model, which can be used to get the repository or store the model in it.
These 3 methods are defined in the ModelWithRepository
interface:
/**
* Interface of a model with a repository.
*/
interface ModelWithRepository
{
/**
* Get the model repository name.
*/
getRepositoryName(): string;
/**
* Get the model repository.
*/
getRepository(): ModelRepository;
/**
* Store the model in its repository.
*/
store(): void;
}
When a model is linked to a repository, you can use find
to get instances from it or retrieve it elsewhere (from an API, for example).
const author = await find(Author, "example@example.example", async (email: string) => {
// Make an API call or something like that to retrieve the model and store it in the repository.
// ...
return model;
});
To help generalization of API calls for a given model, you can implement an automatic retriever of a model.
class Author extends WithRepository("Author")(Model) implements AutoRetriever<Author>
{
async autoRetrieve(identifier: unknown): Promise<Author>
{
return (new Author()).deserialize({
// ... make an API call to retrieve serialized data, for example ...
});
}
// ... the rest of the definition ...
}
Sharkitek Repositories also provide a special model property type, that automatically uses repositories
to store and retrieve instances. When you use SModelFromRepository
property type, on deserialization, Sharkitek
will first try to get an instance matching the model identifier in its repository. If it is not found, then it will use
the currently serialized instance of the model as the main instance and store it in the repository.
Here is an example:
class A extends WithRepository("A")(Model)
{
@Property(SNumeric)
@Identifier
id: number = undefined;
@Property(SString)
foo: string = undefined;
}
class B extends Model
{
@Property(SNumeric)
@Identifier
id: number = undefined;
@Property(SModelFromRepository(A))
a: A = undefined;
}
// First deserialization, that should store the A instance.
const firstB = (new B()).deserialize({
id: 5,
a: {
id: 3, // No instance with ID 3 is stored in the repository, using this instance and storing it.
foo: "first",
}
});
// To check that the first instance of "A" is used, we change the value of "foo". If a.foo == "first", then the first object has been used.
const secondB = (new B()).deserialize({
id: 7,
a: {
id: 3, // Same ID as the previous object, using the instance from repository.
foo: "second",
}
});
console.log(firstB.a.foo); // Result: "first".
console.log(secondB.a.foo); // Result: "first".
// firstB.a and secondB.a are the same object.
firstB.a.foo = "test";
console.log(secondB.a.foo); // Result: "test".