Skip to content

update client arch docs for team-owned libs #259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ hotfixes
inet
IntelliJ
Iterm
incentivizing
jslib
jumpcloud
keychain
Expand Down
63 changes: 63 additions & 0 deletions docs/architecture/adr/0022-team-owned-libs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
adr: "0022"
status: In progress
date: 2023-01-09
tags: [clients]
---

# 0022 - Team-owned libs

<AdrTable frontMatter={frontMatter}></AdrTable>

## Context and Problem Statement

Historically, much of the feature logic of Bitwarden has existed within the `apps/` directories,
only being moved to `libs/` (usually `libs/common/` or `libs/angular/`) if it needed to be shared
between multiple clients.

This pattern makes it more difficult for teams to independently manage code they own.

## Considered Options

- **Do nothing** - Keep our current pattern.
- **Template-driven forms** - Move functionality out of `apps/`, `libs/common/`, and `libs/angular/`
and move into libs that are smaller, feature-focused, and owned by a team.

This is informed by [Nx](https://nx.dev/concepts/more-concepts/applications-and-libraries), a
monorepo tool:

> A typical Nx workspace is structured into "apps" and "libs". This distinction allows us to have a
> more modular architecture by following a separation of concerns methodology, incentivizing the
> organization of our source code and logic into smaller, more focused and highly cohesive units.

<blockquote>
A common mental model is to see the application as "containers" that link, bundle and compile functionality implemented in libraries for being deployed. As such, if we follow a 80/20 approach:

- place 80% of your logic into the libs/ folder
- and 20% into apps/

Note, these libraries don’t necessarily need to be built separately, but are rather consumed and
built by the application itself directly. Hence, nothing changes from a pure deployment point of
view.

</blockquote>

## Decision Outcome

Chosen option: **Team-owned libs**

### Positive Consequences

- **Clear public API** - Each team can decide what is public and private within their library. This
prevents teams from relying on code that is meant to be internal.
- **More team autonomy** -
- **Easier to share code between apps** -
- **Clearer dependency graph** - It will be easier to inspect which teams are relying internal and
external dependencies.
- **Simplified code ownership** -
- **Incremental builds** -

### Negative Consequences

- **Managing circular dependencies** -
- **More boilerplate** -
69 changes: 58 additions & 11 deletions docs/architecture/clients/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,65 @@ and a single [Git repository](https://github.com/bitwarden/clients).

The mono-repository root directory contains three main folders.

- `apps` - Our different application specific code, consists of `web`, `browser`, `desktop` and
- `apps`: Our different application specific code, consists of `web`, `browser`, `desktop` and
`cli`.
- `bitwarden_license` - Bitwarden Licensed version of the web vault.
- `libs` - Shared code between the different applications.

`libs` contains the following projects.

- `Common` - Common code shared between all the clients including CLI.
- `Angular` - Angular specific code used by all the visual clients.
- `Components` - Angular Components Library.
- `Node` - Used to be shared code for CLI and Directory Connector CLI, but since directory connector
no longer uses the same version of libs this module is deprecated.
- `bitwarden_license`: Bitwarden Licensed version of the web vault.
- `libs`: Shared code between the different applications.

## Libs

Historically, much of the feature logic of Bitwarden has existed within the `apps/` directories,
only being moved to `libs/` (usually `libs/common/` or `libs/angular/`) if it needed to be shared
between multiple clients.

We are attempting to move to a more modular architecture by creating additional libs that are more
feature-focused and which more accurately convey team code ownership.

- `common`: Common code shared between all the clients including CLI
- `angular`: Low-level Angular utilities used by all the visual clients
- `node`: Used to be shared code for CLI and Directory Connector CLI, but since directory connector
no longer uses the same version of libs this module is deprecated
- `admin-console`: Code owned by the Admin Console team
- `auth`: Code owned by the Auth team
- `billing`: Code owned by the Billing team
- `components`: Angular implementation of the Bitwarden design system
[See more.](https://components.bitwarden.com/)
- `exporter`: Code related to exporting; owned by the Tools team
- `importer`: Code related to importing; owned by the Tools team
- `platform`: Code owned by the Platform team
- `vault`: Code owned by the Vault team

### Background

More on this approach can be found in the
[Nx documentation](https://nx.dev/concepts/more-concepts/applications-and-libraries):

> place 80% of your logic into the `libs/` folder and 20% into `apps/`

We are doing the opposite of this right now. The code that remains in `apps/` should be primarily
concerned with bootstrapping the application and consuming and configuring code exported from
`libs/`. Over time, code not meeting this criteria should be moved from `apps/` to `libs/`.

Any code in the `apps/` that doesn't have a tight coupling with the client can be moved into a lib:
if an exported member is wholly dependent on other libs but not `apps/`, it can likely be moved to a
lib itself. (More concretely, this bars components that rely on global client-specific CSS — but not
components built with Tailwind and the CL — from being included in a lib)

> Having a dedicated library project is a much stronger boundary compared to just separating code
> into folders, though. Each library has a so-called "public API", represented by an index.ts barrel
> file. This forces developers into an "API thinking" of what should be exposed and thus be made
> available for others to consume, and what on the others side should remain private within the
> library itself.

An existing example of this pattern is `@bitwarden/components`:

- It is consumed by multiple apps and other libs
- It manages a clear public and private API boundary through its barrel file
- Code ownership is clear — the CL team only owns the files within `libs/components`
- The CL team can make independent decisions around internal folder structure and code style

As part of this process, we are also investigating utilizing additional tooling (such as Nx) to make
creating new libs on the fly easier.

## Package Diagram

Expand Down