Skip to content
Merged
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 .fernignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Specify files that shouldn't be modified by Fern
changelog.md
migration-from-vital/
97 changes: 97 additions & 0 deletions migration-from-vital/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Changelog

_Major release. Baseline: `tryVital/vital-python@2.1.561`._

## Breaking changes

- **Minimum Python is now 3.10** — [migration steps](MIGRATION.md#install)
The new distribution requires Python 3.10 or newer (previously 3.8). Older interpreters can no longer install or import the SDK. Bump your project's runtime, your CI matrix, your Dockerfile base images, and any tooling that pins the interpreter (e.g. `tool.poetry.dependencies.python`, `setup.cfg python_requires`, `pyenv` files).
- **Package renamed: `vital` → `junction-api-sdk`** — [migration steps](MIGRATION.md#install)
The PyPI distribution name has changed. Uninstall the old package and install `junction-api-sdk`, then update every import path in your codebase from `vital` to `junction`. This is a *replacement*, not a version bump — the old `vital` distribution is no longer published with new releases.
- **Tighter `pydantic-core` upper bound (`<2.44.0`)** — [migration steps](MIGRATION.md#install)
The dependency on `pydantic-core` is now pinned to `>=2.18.2,<2.44.0`. If your application or another dependency requires `pydantic-core >= 2.44.0`, the install will fail to resolve. Audit your lockfile and any sibling packages that pull in newer `pydantic-core` versions before upgrading.
- **Server base URLs replaced (Environment enum also renamed)** — [migration steps](MIGRATION.md#rename-environment-enum)
The SDK now talks to the rebranded Junction hosts. The four server URLs have been replaced:

- `api.tryvital.io` → `api.us.junction.com`
- `api.eu.tryvital.io` → `api.eu.junction.com`
- `api.sandbox.tryvital.io` → `api.sandbox.us.junction.com`
- `api.sandbox.eu.tryvital.io` → `api.sandbox.eu.junction.com`

This affects any caller that passes a literal URL string for the `base_url` argument or otherwise references the old hosts (allow-lists, monitoring, log filters). The environment enum has also been renamed:

- `VitalEnvironment` → `JunctionEnvironment`

Callers that use the enum (e.g. `JunctionEnvironment.PRODUCTION`) automatically pick up the new URL because the enum's underlying value changed alongside the rename.

- **Top-level client class renamed to `Junction` / `AsyncJunction`** — [migration steps](MIGRATION.md#rename-client-class)
The synchronous and asynchronous client classes have been renamed:

- `Vital` → `Junction`
- `AsyncVital` → `AsyncJunction`

Update every construction site and every type annotation that references the old names. The constructor keyword arguments (`api_key`, `base_url`, `environment`, `timeout`, `httpx_client`, …) are unchanged.
- **Request bodies and path parameters are now inline keyword arguments** — [migration steps](MIGRATION.md#inline-request-fields)
Methods that used to take a single `request=<RequestModel>` object alongside path parameters now expose every body field and path parameter directly on the method signature. Pass each field as a keyword argument (or, for path parameters, as a positional argument) instead of building a request model. The change applies uniformly across the SDK; for example:

```python
# Before
lab_tests.book_phlebotomy_appointment(order_id, request=AppointmentBookingRequest(booking_key=...))

# After
lab_tests.book_phlebotomy_appointment(order_id, booking_key=...)
```

Required body fields become required keyword arguments; optional body fields become optional keyword arguments with the same names.
- **Some response and request fields are now `Optional`** — [migration steps](MIGRATION.md#nullable-fields)
Fields whose schemas are marked nullable in the API definition are now exposed as `Optional[...]` in Python types and may legitimately be `None`. If you have type-checked code that previously relied on these fields being non-`None`, add a guard (or update your type hints) before dereferencing them. This affects both response model attributes and the corresponding request inputs; the wire format is unchanged.

## New & improved

- **New top-level resources**
The SDK now exposes the `compendium`, `lab_account`, `order_transaction` resource clients on the root client. See the API reference for the full endpoint list.
- **Raw response shapes formalized — `*V2InDb` types are now `*Raw`**
Endpoints whose responses were previously typed as `*V2InDb` now use `*Raw` types. The values are unchanged; only the type names differ:

- `ActivityV2InDb` → `ActivityRaw` (for `activity.get_raw`)
- `BodyV2InDb` → `BodyRaw` (for `body.get_raw`)
- `DeviceV2InDb` → `DevicesRaw` (for `devices.get_raw`)
- `SleepV2InDb` → `SleepRaw` (for `sleep.get_raw`)
- `WorkoutV2InDb` → `WorkoutRaw` (for `workouts.get_raw`)

Additionally, the standalone `RawDevices` wrapper from the old SDK is replaced by `RawDevicesResponse`.

If you imported one of the old type names directly (e.g. `from junction.types.activity_v_2_in_db import ActivityV2InDb`), switch to the new `Raw` type.
- **Configurable SDK logging**
Both `Junction` and `AsyncJunction` accept a new `logging` keyword argument (`LogConfig` or a custom `Logger`). Pass a `LogConfig` to set the log level (`debug` / `info` / `warn` / `error`) and toggle silent mode, or supply your own `Logger` implementation to integrate with an existing application logger. By default the SDK is silent.
- **Optional `aiohttp` async transport**
An opt-in `aiohttp` extra is available: `pip install "junction-api-sdk[aiohttp]"`. Installing it pulls in `aiohttp` and `httpx-aiohttp`, and lets you pass `httpx_client=DefaultAioHttpClient(...)` from `junction._default_clients` to the async client to use an aiohttp-backed transport. Existing users do not need to install the extra.

## Removed

- **Legacy link methods removed** — [migration steps](MIGRATION.md#link-removed-legacy-methods)
These methods have been deprecated for over two years and were never part of the documented Junction Link integration path; they should not have been in the SDK in the first place. They are removed in this release:

- `link.email_auth`
- `link.password_auth`
- `link.start_connect`
- `link.connect_manual_provider`
- `link.token_state`
- `link.is_token_valid`
- `team.get_link_config`

The supporting request/body classes that backed these methods are removed alongside them:

- `BeginLinkTokenRequest`
- `EmailAuthLink`
- `PasswordAuthLink`
- `LinkTokenValidationRequest`
- `ManualConnectionData`

If you have call sites referencing these methods, see the Junction Link API reference for the documented integration path.
- **Public types removed** — [migration steps](MIGRATION.md#public-types-removed)
Three top-level type re-exports were removed from the SDK with no equivalent. If you imported any of these from the package root, drop the import:

- `AuthType` — was used by the legacy `email_auth` flow only.
- `ManualProviders` — was the parameter type for the now-removed `connectManualProvider` method (one of the legacy link methods, see above). With that method gone, this enum is removed too.
- `ClientFacingUserKey` — the endpoint that used to return this model now returns `ClientFacingUser` instead. If you depended on the user-key shape, switch to reading the user fields off `ClientFacingUser` directly.
204 changes: 204 additions & 0 deletions migration-from-vital/MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# Migration guide

_From `tryVital/vital-python@2.1.561` to the new release._

## Install the new package

<a id="install"></a>

This is a *replacement*, not a version bump — uninstall the old distribution, install `junction-api-sdk`, and update your imports from the old package name to the new one. The minimum Python version is now 3.10.

Things to watch for:

- Aliased imports (`import vital as v`, `from vital import types as vt`).
- Submodule imports across `vital.lab_tests`, `vital.user`, `vital.link`, `vital.types`, `vital.errors`, etc.
- String-literal references in dynamic loaders (`importlib.import_module("vital....")`, entry-point specs in `pyproject.toml` / `setup.py`, dependency-injection container keys).
- Lockfiles, Dockerfile pins, CI/CD scripts, and internal mirror/proxy index entries that reference the old `vital` distribution.
- Version introspection: `importlib.metadata.version("vital")` becomes `importlib.metadata.version("junction-api-sdk")`.
- Environment-variable names following the old brand (e.g. `VITAL_API_KEY`); the SDK constructor argument names are unchanged but your application's own env-var conventions may need a rename pass.

**Before:**

```bash
pip install vital
```

```python
from vital import Vital
client = Vital(api_key="YOUR_API_KEY")
```

**After:**

```bash
pip uninstall vital
pip install junction-api-sdk
```

```python
from junction import Junction
client = Junction(api_key="YOUR_API_KEY")
```

## Server base URLs and `VitalEnvironment` → `JunctionEnvironment`

<a id="rename-environment-enum"></a>

The four server URLs are replaced as follows:

| Old host | New host |
|-----------------------------------|-----------------------------------------|
| `api.tryvital.io` | `api.us.junction.com` |
| `api.eu.tryvital.io` | `api.eu.junction.com` |
| `api.sandbox.tryvital.io` | `api.sandbox.us.junction.com` |
| `api.sandbox.eu.tryvital.io` | `api.sandbox.eu.junction.com` |

Things to watch for:

- Hard-coded URL strings in `base_url=`, allow-lists, monitoring dashboards, log filters, and webhook signatures.
- Outbound-egress firewall rules and proxy configurations pinned to the old hostnames.
- `VitalEnvironment` references in test fixtures and CI configuration.

**Before:**

```python
from vital import Vital
from vital.environment import VitalEnvironment

client = Vital(
api_key="YOUR_API_KEY",
environment=VitalEnvironment.PRODUCTION,
)

# or, when overriding with a literal URL:
client = Vital(api_key="YOUR_API_KEY", base_url="https://api.tryvital.io")
```

**After:**

```python
from junction import Junction
from junction.environment import JunctionEnvironment

client = Junction(
api_key="YOUR_API_KEY",
environment=JunctionEnvironment.PRODUCTION,
)

# or, when overriding with a literal URL:
client = Junction(api_key="YOUR_API_KEY", base_url="https://api.us.junction.com")
```

## Rename `Vital` / `AsyncVital` to `Junction` / `AsyncJunction`

<a id="rename-client-class"></a>

Things to watch for:

- Aliased imports (e.g. `from vital import Vital as VitalClient`).
- Type annotations on helpers that take a client argument (`def fn(client: Vital) -> ...`).
- String-literal references in dynamic dispatch, dependency-injection containers, or pickle/serialization layers.
- `isinstance(...)` checks against the old class.

**Before:**

```python
from vital import Vital, AsyncVital

client = Vital(api_key="YOUR_API_KEY")
async_client = AsyncVital(api_key="YOUR_API_KEY")
```

**After:**

```python
from junction import Junction, AsyncJunction

client = Junction(api_key="YOUR_API_KEY")
async_client = AsyncJunction(api_key="YOUR_API_KEY")
```

## Pass body and path fields as inline arguments

<a id="inline-request-fields"></a>

The same rule applies to every method that previously took a `request=` model: lift each body field onto the method as a keyword argument, and pass path parameters positionally (or as the keyword name shown in the new docstring). You generally no longer need to import the per-endpoint request model classes.

**Before:**

```python
from vital import Vital
from vital.types import AppointmentBookingRequest

client = Vital(api_key="YOUR_API_KEY")

client.lab_tests.book_phlebotomy_appointment(
order_id="order_123",
request=AppointmentBookingRequest(
booking_key="slot_abc",
),
)
```

**After:**

```python
from junction import Junction

client = Junction(api_key="YOUR_API_KEY")

client.lab_tests.book_phlebotomy_appointment(
"order_123",
booking_key="slot_abc",
)
```

## Handle `Optional` response fields

<a id="nullable-fields"></a>

Audit any callsite that previously dereferenced a field whose schema is now nullable. The set of affected fields is whatever the API definition marks `nullable: true`; type checkers will flag the new `Optional[...]` annotations once you upgrade.

**Before:**

```python
order = client.lab_tests.get_order(order_id="order_123")
upper_name = order.shipping_recipient_name.upper()
```

**After:**

```python
order = client.lab_tests.get_order(order_id="order_123")
upper_name = order.shipping_recipient_name.upper() if order.shipping_recipient_name is not None else None
```

## Drop calls to the legacy link methods

<a id="link-removed-legacy-methods"></a>

These methods were deprecated for years and not part of the documented Junction Link integration. Customer code that didn't reference them needs no migration. If you do have call sites, replace them with the Junction Link integration described in the API reference — there isn't a one-to-one drop-in, the legacy methods wrapped retired endpoints with no published equivalents.

## Drop imports for removed public types

<a id="public-types-removed"></a>

Three names were exported from the package root in the old SDK but are not present in the new SDK:

- `AuthType` — was only used by the legacy `email_auth` flow.
- `ManualProviders` — was the parameter type for the now-removed `connectManualProvider` method.
- `ClientFacingUserKey` — callers should switch to `ClientFacingUser`. The endpoint that previously returned `ClientFacingUserKey` now returns `ClientFacingUser`.

**Before:**

```python
from vital import AuthType, ClientFacingUserKey, ManualProviders
```

**After:**

```python
# AuthType and ManualProviders have no replacement — remove the import.
# ClientFacingUserKey -> ClientFacingUser
from junction import ClientFacingUser
```
Loading