From 6f7b2fa81dbb384aed46f2dfe962b53130cbb465 Mon Sep 17 00:00:00 2001 From: Madeorsk Date: Thu, 4 Aug 2022 15:06:41 +0200 Subject: [PATCH] New README with documentation. --- README.md | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 741a670..ebc3734 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,139 @@ -# repositories +# Sharkitek Repositories -Sharkitek repositories extension. \ No newline at end of file +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. + +```typescript +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: + +```typescript +/** + * 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). + +```typescript +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. + +```typescript +class Author extends WithRepository("Author")(Model) implements AutoRetriever +{ + async autoRetrieve(identifier: unknown): Promise + { + 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: + +```typescript +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". +```