# Monorepo

import { REACT_VERSION, EFFECT_VERSION } from '../../../../../../packages/@local/shared/src/CONSTANTS'

## Prerequisites

### Personal experience

Depending on the kind of contribution you're interested in, the following
experience is recommended:

- Deep experience with TypeScript (incl. type-level programming)
- Experience with TypeScript monorepo setups
- Experience with distributed systems
- Experience with [Effect](https://effect.website) (or willingness to learn)

### Recommended tooling: Use devenv + direnv for a consistent setup

To make development easy and consistent across systems and platforms, this
project uses [Nix](https://zero-to-nix.com/) with [devenv](https://devenv.sh)
to manage "system dependencies" such as Node.js, Bun, etc.
Use [direnv](https://direnv.net) (recommended) to automatically load the
environment, or run commands explicitly with devenv, for example:
`devenv shell pnpm install`.

### Manual setup

You'll need to have a recent version the following tools installed:

- Node.js
- Bun
- pnpm

## Initial setup

```bash
git clone git@github.com:livestorejs/livestore.git
cd livestore
# Loads env vars, installs deps and builds the project
./bootstrap.sh
```

## General notes

- TypeScript
  - LiveStore tries to follow the strictest TypeScript rules possible to ensure
    type safety and avoid subtle bugs.
    - LiveStore also makes heavy use of
      [TypeScript project references](https://www.typescriptlang.org/docs/handbook/project-references.html).
- Package management
  - This project uses [pnpm](https://pnpm.io/) to manage the workspace.
- LiveStore is primarily developed in VSCode/Cursor.
- Testing
  - LiveStore uses Vitest for most tests and Playwright for browser tests.

### Notable used tools / technologies

- [TypeScript](https://www.typescriptlang.org/)
- [Effect](https://effect.website)
- [pnpm](https://pnpm.io/)
- [Bun](https://bun.sh/)
- [Vitest](https://vitest.dev/)
- [Playwright](https://playwright.dev/)
- [OpenTelemetry](https://opentelemetry.io/)
- [wa-sqlite](https://github.com/rhashimoto/wa-sqlite) (included as git subtree) - see [wa-sqlite management](../../../../../../contributor-docs/wa-sqlite-management.md)
- [Nix](https://zero-to-nix.com/)
- [Direnv](https://direnv.net/)
- [devenv](https://devenv.sh)

### Environment variables

The `.envrc` file contains all necessary environment variables for the project.
You can create a `.envrc.local` file to override or add variables for your local
setup. You'll need to run `direnv allow` to load the environment variables.

### VSCode tasks

- This project is primarily developed in VSCode and makes use of
  [tasks](https://code.visualstudio.com/docs/editor/tasks) to run commands.
- Common tasks are:
  - `dev:ts:watch` to run the TypeScript compiler in watch mode for the entire
    monorepo
  - `pnpm:install` to install all dependencies (e.g. when changing a
    `package.json`)

## Tasks to run before committing

Please run the following tasks before committing & pushing:

- `mono ts` to build the TypeScript code
- `mono lint` to run the linting checks
- `mono test` to run the tests

## Examples

- Once you've set up the monorepo locally, you'll find all examples in the
  `/examples` directory.
- All examples are self-contained and can be run independently.
- Examples use explicit version dependencies (e.g., `0.3.2-dev.0`) for LiveStore packages.
- Examples are not part of the monorepo TypeScript build system to maintain independence.
- Each example has its own TypeScript configuration that's independent of the
  monorepo build system.

#### Making changes to examples

1. Make your desired changes directly in `/examples/<example-name>`.
2. Test your changes by running the example (e.g., `pnpm dev` in the example
   directory).
3. Commit your changes.

### OpenTelemetry setup

As a local OpenTelemetry setup, we recommend the
[docker-otel-lgtm](https://github.com/grafana/docker-otel-lgtm) setup.

Add the following to your `.envrc.local` file:

```bash
export VITE_GRAFANA_ENDPOINT="http://localhost:30003"
export GRAFANA_ENDPOINT="http://localhost:30003"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
export VITE_OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
```

### TypeScript

- Each package has its own `tsconfig.json` file which extends the root
  `tsconfig.base.json`.
- This project makes heavy use of TypeScript project references.

### Package management

- This project uses [pnpm](https://pnpm.io/) to manage the workspace.
- We're using the `workspace:*` protocol to link packages together.
- We should try to keep dependencies to an absolute minimum and only add them if
  we absolutely need them.
- We also need to manually add peer dependencies for each package.
- We should try to avoid duplicate dependencies across the monorepo as much as
  possible as duplicate dependencies can lead to a lot of issues and pain.
  - We're also using the `resolutions` field in the root `package.json` to force
    some packages to be the same across the monorepo (ideally not needed but for
    some packages it's necessary currently).
- We're using [syncpack](https://github.com/JamieMason/syncpack) to help
  maintain consistent dependency versions across the monorepo.
  - See `syncpack.config.mjs` for the configuration.
  - Common commands:
    - `bunx syncpack format` to format the `package.json` files
    - `bunx syncpack lint` to check all version ranges
    - `bunx syncpack fix-mismatches` to adjust versions across `package.json`
      files (check before with `lint`)
    - `bunx syncpack update` to update packages across the monorepo to the
      latest versions

### Notes on external dependencies

LiveStore tries to use as few external dependencies as possible. Given LiveStore
is built on top of Effect, which can be considered a standard library for
TypeScript, it should handle most use cases.

#### Notes on some packages

The following packages need to be updated with extra care:

- `react`/`react-dom` as we need to move in lockstep with Expo / React Native
  (currently pinned to {REACT_VERSION})
- `effect` (currently pinned to {EFFECT_VERSION})

#### Effect

- LiveStore makes heavy use of the [Effect](https://effect.website) library and
  ecosystem throughout the implementation of the various packages.
- Effect is not imposed on the app developers using LiveStore but where it makes
  sense, LiveStore is also exposing a Effect-based API (e.g. `createStore`).

#### Updating dependencies

- Either update the versions manually in each `package.json` file or use
  `bunx syncpack update`.

### Notes on monorepo structure

- The `@livestore/utils` package re-exports many common modules/functions (e.g.
  from `effect`) in order to
  - Reduce the number of direct dependencies for other packages
  - Allows for convenient extension of modules (e.g. adding methods to
    `Effect.___`, `Schema.___`, ...)

## Docs

The LiveStore docs are built with
[Astro Starlight](https://starlight.astro.build/).

## Related external repos

- [Fork of wa-sqlite](https://github.com/livestorejs/wa-sqlite) with Nix build setup included as git subtree.
- The source code of the devtools is currently not part of this monorepo but in
  a separate private repo.