Skip to content

Commit 06e26a6

Browse files
committed
ADR-9: cardano-api-exports convention
1 parent 49fa4ca commit 06e26a6

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Status
2+
3+
✅ Accepted 21-02-2025
4+
5+
# Context
6+
7+
The current module structure of `cardano-api` is very ad-hoc.
8+
It is not clearly defined where modules should be placed and how to be exported.
9+
This ADR aims to standardise this process.
10+
11+
# Decision
12+
13+
## Top level exports
14+
15+
Each top level export should export distinct symbols.
16+
This may depend on the case, for example: `Cardano.Api.Byron` symbols which are still in use in current eras, can be reexported through `Cardano.Api`.
17+
18+
* `Cardano.Api` - everything domain related for the currently used and upcoming eras
19+
20+
* `Cardano.Api.<F>`, where `<F>` represents a feature.
21+
An aggregate module providing one of core `cardano-api` functionalities.
22+
The name has to be a singular noun.
23+
The purpose of this export is to provide users a more granular control of imports if they don't want to import a catch-all `Cardano.Api` module.
24+
For example:
25+
26+
* `Cardano.Api.Address`
27+
* `Cardano.Api.Block`
28+
* `Cardano.Api.Certificate`
29+
* `Cardano.Api.Eon`
30+
* `Cardano.Api.Genesis`
31+
* `Cardano.Api.Governance`
32+
* `Cardano.Api.IPC`
33+
* `Cardano.Api.Key`
34+
* `Cardano.Api.LedgerState`
35+
* `Cardano.Api.Query`
36+
* `Cardano.Api.Serialisation`
37+
* `Cardano.Api.Tx`
38+
39+
The following rules apply:
40+
41+
1. The modules should not be very granular, only related to a particular feature set.
42+
For example
43+
44+
* `Cardano.Api.Governance.Actions.ProposalProcedure` should not be a top level export and should be exported through `Cardano.Api.Governance`.
45+
* `Cardano.Api.LedgerEvents` should not be a top level export and should be exported through `Cardano.Api.LedgerState`.
46+
47+
1. The module should be reexported through `Cardano.Api`.
48+
This makes using `cardano-api` easier, by not forcing users to decide what to import, and allowing them to just simply write `import Cardano.Api`.
49+
50+
* `Cardano.Api.Byron` - everything for the obsoleted Byron era
51+
52+
* `Cardano.Api.Compatible` - everything for the older eras.
53+
The purpose of this module to provide a limited backwards compatibility for eras not in use on Cardano mainnet.
54+
This is meant only for supporting of tests which hardfork through eras.
55+
56+
For both `Cardano.Api.Byron` and `Cardano.Api.Compatible` the following rules apply:
57+
58+
1. Any symbol from previous era, not in use in current era, should be exported through the respective module for older eras.
59+
2. Any symbol from previous era and still in use in the current era, should be exported through `Cardano.Api` and additionally through `Cardano.Api.(Byron|Compatible)`.
60+
61+
* `Cardano.Api.Experimental` - a transient module for implementing new not yet stabilised APIs.
62+
Not meant to be used by `cardan-api` users directly.
63+
64+
* `Cardano.Api.<U>` utility module, where `<U>` represents a utilities set.
65+
For example `Cardano.Api.Pretty`, `Cardano.Api.Monad.Error`.
66+
67+
* Reexports from upstream libraries like consensus, network or ledger, also fall into this category e.g. `Cardano.Api.Ledger`.
68+
69+
* Modules which are exposing general purpose classes and functions should go also into a separate module, and they don't need to be reexported through `Cardano.Api`.
70+
For example `Cardano.Api.Tx.UTxO` - a wrapper type, with functions common to maps which would clash with other map data structures.
71+
A good example of this pattern from Hackage is [`Data.Aeson.KeyMap`](https://hackage.haskell.org/package/aeson-2.2.3.0/docs/Data-Aeson-KeyMap.html).
72+
73+
In principle, those should not be reexported from `Cardano.Api`, because they would pollute symbol namespace, and are not required for using `cardano-api` core features but can be useful for the advanced users.
74+
In certain situations, parts of those modules can be reexported from `Cardano.Api`, to provide more seamless experience of using the main `Cardano.Api` module.
75+
76+
## Deeper level exports
77+
78+
Any other modules not meant to be a top level export, should be placed inside `Cardano.Api.Internal` or `Cardano.Api.<X>.Internal` and be reexported through a suitable top level module.
79+
In general internal modules shouldn't be exposed in cabal package, but it may be necessary for using them from other components in `cardano-api`, like tests.
80+
This however depends on the specific use case.
81+
`Internal` in the module name should indicate that the module isn't really meant to be used directly, and users can expect more frequent breakage when relying on it.
82+
83+
* `Cardano.Api.<X>.Internal` or `Cardano.Api.Internal.<X>` or should contain everything related to the domain `<X>`.
84+
* If `Cardano.Api.<X>` is a top level export, internal functions should go to `Cardano.Api.<X>.Internal` (e.g. `Cardano.Api.Address.Internal`), otherwise
85+
* if there's no `Cardano.Api.<X>` top level export, internal functions should go to `Cardano.Api.Internal.<X>` (e.g. `Cardano.Api.Internal.Orphans`).
86+
87+
A good example from Hackage how to nest `Internal` modules is [`text`](https://github.com/haskell/text/blob/master/src/Data/Text/Internal/Builder/RealFloat/Functions.hs) package.
88+
89+
# Consequences
90+
91+
Acceptance of ADR will require rename of almost all cardano-api modules which will be a breaking change.
92+

0 commit comments

Comments
 (0)