# Where packages live

`packages/` holds only packages you installed. Code your app's authors
wrote lives where the rest of their code lives, whatever kind it is:

```text
app.jadpo
domains/
    shipping/libraries/...           the app's helpers for one domain
shared/
    libraries/...                    the app's helpers for several domains
    providers/
        acme_couriers/v1/            the app's own integration, in the package format
packages/                            installed only: in jadpo.lock, read-only
    stripe/v2024_06_20/
    postcodes/v2/
jadpo.lock
```

- **Installed packages are committed** under `packages/<name>/<version>/`.
  Agents read them with the tools they already use, reviewers see an
  upgrade as an ordinary diff (its surface diff included), and CI needs no
  fetch step. A build never fetches anything.
- **Installed packages are read-only.** The compiler refuses one whose
  files don't match its digest in `jadpo.lock`. A digest is a fingerprint
  of the files, so any change to them shows.
- **Your app's own integrations live in
  `shared/providers/<name>/<version>/`**, in exactly the package format.
  They can have everything an installed provider can: types, failures,
  pure functions, decoding, recordings, fakes, `provide` mappings, actions,
  subscribers and services. Who may call one is still decided by the
  connection's `domains:` list.
- **A `use` line shows where a name comes from.** `use packages/postcodes`
  is always installed code, and `use shared/providers/acme_couriers` is
  the app's own. The only differences between the two are where the code
  sits, whether you can edit it and whether the publishing bar applies. So
  replacing your own integration with an official package later changes
  `jadpo.lock`, the folder and the `use` lines, and not the code that
  calls it.
- **Publishing moves code out of the app.** A package other apps depend on
  gets its own repository and versions. Every app installs it into
  `packages/`, the one it started in included.

## Two versions side by side

Two versions of one package can be held at once: a provider during an
upgrade, a candidate version while the upgrade plan compiles the app
against it, or two library versions while callers move across. Each is
its own package in its own folder, both installed or both the app's own.
While two are held, every name written through either carries its
version, such as `Postcodes.v3.UkPostcode`. One `use` line brings in both,
because it names the package's folder.

Here the app's own `Postcodes` is held at `v2` and `v3` while callers move
across:

```jadpo
/// Reading UK postcodes.
public library uk {
    /// Reads a UK postcode as it is written, spaces around it left out.
    function standard_form(postcode_text: WrittenPostcode) fails InvalidPostcode -> UkPostcode {
        return attempt UkPostcode(text.upper(text.trim(postcode_text))) {
            invalid: InvalidPostcode
        }
    }
}
```

```jadpo
use shared/providers/postcodes

/// Reads a customer's postcode, as callers did before the upgrade.
action read_postcode(
    written: Postcodes.v2.WrittenPostcode
) fails Postcodes.v2.InvalidPostcode -> Postcodes.v2.UkPostcode {
    return attempt Postcodes.v2.uk.standard_form(written)
}
```

```jadpo
use shared/providers/postcodes

/// Reads a customer's postcode with the next version.
action read_typed_postcode(
    written: Postcodes.v3.WrittenPostcode
) fails Postcodes.v3.InvalidPostcode -> Postcodes.v3.UkPostcode {
    return attempt Postcodes.v3.uk.standard_form(written)
}
```

A name without its version while two are held is
`package.version_needed`. Once the old version goes, a name that still
carries the version is `package.version_unneeded`, whose suggested edit
drops it. Both are listed under "Package errors".

While two versions of a library package that carries translations are
held, the app words each under a key that carries the version,
`postcodes_v3: { }`, as its names do
([Jadpo's and packages' text](failures-for-client-apps.md#jadpos-and-packages-text)).

## Names

- **Provider brand names are reserved.** Jadpo ships the list of curated
  provider names, and an app's own integration cannot take one, so `Stripe`
  in code always means the official package.
- **Two packages never share a name in code.** Installing a registry package
  whose name one of the app's own integrations or libraries already uses
  stops and asks for the app's own to be renamed first (`jadpo rename`).
- **A package's name can't clash with any other name.** Domain, library
  and standard-library names are unique among themselves, and a package's
  name joins them. Installing a package refuses one whose name the app
  already uses for a domain, a library or any declaration.
- Creating an integration checks the registry and warns when the name is
  taken.
- A package is named in UpperCamelCase with its own version label, such
  as `Stripe.v2024_06_20` or `Postcodes.v2`. Its folder is the name in
  lower_snake_case with the version below it.
