summaryrefslogtreecommitdiffstats
path: root/doc/src/01010-architecture.md
blob: 1cbaffacc33b771fd315d6711039263fb8fc0dd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# Architecture of the imag code

The imag codebase has a rather simple overall architecture.
In this chapter the types of crates, architecture of an imag module
and the type structure are described.


## Crate types

There are different types of crates in the imag world:

* "core" crates:
    * libimagstore - The imag store is the abstraction over the filesystem. It
      provides primitives to get, write and manipulate store entries and their
      header information.
    * libimagrt - The runtime library, which provides default argument parser
      setup, interfacing with STDIN/STDOUT, configuration loading and parsing.
      Simply put: It provides the runtime for a imag commandline application.
    * libimagerror - Error handling library for handling errors the imag way. Used
      in all other crates, even the store itself. It also offers functionality to
      log and trace errors as well as exiting the application, if necessary.
      (Note: This library might be removed in the future.)
* "entry" crates:
  "Entry" crates provide extensional functionality for the types from
  libimagstore. For example, there is "libimagentrylink" which provides
  functionality to link two entries in the store.
* "domain" crates offer end-user functionality for a imag
  domain, for example "libimagtodo" provides functionality to track todos.
* "etc"/"util" crates for simple utilities.

These are all libraries. There are also binary crates in the imag project
(though they are technically _also_ library crates):

* "core" binary crates, which implement core functionality of imag, such as
  commandline interfaces for tagging, linking, ... entries as well as querying
  them from the store and altering their data.
* "domain" binary crates, which implement a domain such as "todo" handling or
  "calendar" handling.


## Architecture of an imag module

With the things from above, a module could have the following architecture:

```
+-----------------------------------+---------+
|  imag-foo                         |         |
+-----------------------------------+         |
|  libimagfoo                       |         |
+-----------------+-----------------+         |
|                 |                 |         |
| libimagentrybar | libimagentrybaz |         |
|                 |                 |   lib   |
+-----------------+-----------------+         |
|                                   |         |
|  <more library crates>            |         |
|                                   |   imag  |
+-----------------------------------+         |
|                                   |         |
| libimagstore                      |    rt   |
|                                   |         |
+-----------------------------------+---------+
```

External dependencies are not listed in this graphic.

The foundation of all imag modules is the store, as one can see in the
visualization from above.
Above the store level, entry libraries and domain libraries are used to
implement functionality.
The highest level of all imag modules is the commandline interface
on top of the domain library. In between can be any number of entry extension
libraries, or none if not needed.
libimagrt is used by the binary to construct the runtime, which itself
constructs and initializes the Store, so this library is used in the full stack
more or less.

Theoretically, the commandline interface crate could be replaced to build a
terminal user interface, graphical user interface or web interface.


## Types

The imag core, hence the libimagstore and libimagrt, provide a set
of types that a user (as in a library writer) should be aware of.

First of all, there is the `Runtime` type which is provided by the libimagrt. It
provides basic access to whether debugging or verbosity is enabled as well as
the most important core object: The `Store`.

The `Store` type is provided by the libimagstore library, the heart of
everything.

When interacting with the store, two types are visible: `FileLockEntry` and
`Entry` whereas the former derefs to the latter, which basically means that the
former wraps the latter.  The `FileLockEntry` is a necessary wrapper for
ensuring that when working concurrently with the store, an entry is only
_borrowed_ once from the store. It also ensures that the object is alive as long
as the store is.

The `Entry` type provides functionality like reading the actual content, its
header and so on. Extensions for its functionality are implemented on this type,
not on the `FileLockEntry`.

The `Entry` provides access to its header, which is a `toml::Value`, where toml
is the toml-rs crate (external project). Convenience functionality is provided
via the `toml-query` crate, which is an external project which was initiated and
extracted from the imag project.