Arch
#
Installation- npm
- Yarn
#
Use casesIn archimedes we differentiate between queries and commands.
In order to have a query or command you must implement the internalExecute
method and extend from the base class Query
or Command
. This method always returns a promise.
The responsibility of use cases is to orchestrate and call other use cases and business logic. Every action a user can perform should be represented with a use case.
important
To execute a use case you must call the execute
method instead of the internalExecute
.
#
QueriesA query is a use case that gets information from the system (immutable). Queries can have parameters and return something.
You can specify what parameters you can pass as follows:
In case you want to pass more than one parameter you can pass it as an object:
#
CommandsA command is a use case that performs an action or a side effect in the system (mutable). Commands can have parameters and should not return anything
#
SubscribeSometimes you might want to execute some logic whenever a Query or a Command has executed:
In the subscribe callback you can receive additional information like the param
used to execute the use case, the result
and the executionOptions
:
When you subscribe a unique id is returned. This id is used to unsubscribe.
important
Remember to unsubscribe when finished with a use case, if not you might have memory leaks!
#
Execution OptionsWhen you execute a use case you can pass options as the second parameter:
If query or command does not have any parameters you have to pass undefined
:
You can define your own execution options typings by creating a archimedes.d.ts
in the root of your project with the following contents:
If you do so, you can have a type safe way to pass custom options:
#
Chain of responsibilityArchimedes configures a chain of responsibility which allows a use case to be processed through links.
This means that for each action the user performs in your app you can execute arbitrary code, like for example: logging the request, caching data, handling errors and much more in a flexible yet robust way.
In order to create the chain you have to do this as soon as possible in your app:
You can configure the chain however you want, even dynamically:
A complete chain looks like this:
Now, when you create a use case like follows:
And execute it:
The use case will be cached, executed, a log will be shown with the result, the date and if an error happens, the notification center will be notified. And there is even more! You can create custom links.
#
Links#
ExecutorLinkThis link merely executes the use case. It is always needed if you want to execute the use cases.
#
LoggerLinkThis link logs information about the execution of the use case, like parameters, result and name of the use case:
It receives an object that conforms the Logger interface:
For example, the window.console
conforms that interface, so you can either use that:
or any other implementation, like a custom remote logger:
#
NotificationLinkThis link is meant to capture errors occurred when executing a use case. This link should be placed after ExecutorLink
. When an error occurs it will notify the NotificationCenter
. From the UI you can subscribe to the NotificationCenter
in order to show the user an error message:
If you want a use case not to show an error when it fails you can execute the use case with the inlineError
defined in the execution options
#
CacheLinkThis link caches the results for all queries with all parameters combination. To learn more about cache move to cache section.
important
The ExecutorLink
is always required, even if you use the CacheLink
.
important
If you want to use CacheLink
and your framework mangles the name of the classes (like Angular does) you should either disable that option or use the @UseCaseKey
decorator in all your use cases (queries and commands).
For example, to disable name mangling in Angular when you build the application set NG_BUILD_MANGLE=false
in the package.json's script.
To learn more about cache move to cache section.
#
NullLinkThis link throws an error when is called.
#
EmptyLinkThis link does nothing when called.
#
Custom linksYou can create your own custom links by extending the BaseLink class. For instance imagine if we wanted to create a link that starts a spinner when executing an use case:
And then register it in the chain of responsibility:
#
Cacheimportant
It's important to activate emitDecoratorMetadata
to true in the tsconfig.json
compiler's options. See the examples
directory for more information.
#
UseCaseKeyTo manage properly the cache using CacheLink
it is necessary to set a key that identifies each use case. To do this we must use the UseCaseKey
decorator passing as parameter the name we want to give to our use case (we recommend using the same name of the class to simplify).
#
Invalidate cache decoratorYou can automatically invalidate the cache of dependant use cases using the InvalidateCache
decorator in conjunction with the CacheLink
link. If use case a
depends on use case b
, and use case b
depends on use case c
(a
➡ b
➡ c
️) if we invalidate the cache of use case a
we should invalidate the cache of use case b
and c
too. We should add this decorator to all use cases we want this handled.
#
Cache invalidationsIf you want to set that certain commands or queries invalidate the cache of other commands and queries you can set the cache invalidations with CacheInvalidations.set
method. You should indicate the key of the use case that will invalidate the cache and the invalidations that this use case will perform when executed.
These invalidations can be a list of use case keys to invalidate when the first one is executed, for example:
Or you can also use some one of these invalidation policies:
- ALL: The use case will invalidate all the cache of all the use cases
- NO_CACHE: The use case will never be cached
#
Invalidate cache in runtimeSometimes you want to execute a Query invalidating the cache for this specific execution, for example, refresh an email list. To do that, you can use invalidateCache: true
in the execution options object.