|
| 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