npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@affinity-health/effect-sdk

v0.4.0

Published

Effect-native TypeScript SDK for the Affinity API

Readme

Affinity Effect SDK

Effect-native TypeScript SDK and local code runner for the Affinity API. The repository generates 83 typed operations and runtime schemas: 74 public operations from the deployed API contract and the 9 existing internal pricing and formulation operations.

Install

bun add @affinity-health/effect-sdk [email protected]

Set the API key in the process environment. The CLI never accepts secrets as flags.

affinity auth login
# Request read and write access.
affinity auth login --access write

The CLI opens Affinity's browser approval page, polls using OAuth device authorization, and stores the resulting expiring credential in the user's configuration directory with owner-only permissions. Inspect or revoke it without exposing the token:

affinity auth status --json
affinity auth logout

A device login can authorize one or more organizations. Select an organization for each command:

affinity context --json
affinity eval 'await affinity.getAccount({})' --organization org_example

When the login contains one organization, the CLI selects it automatically. For repeated work, set AFFINITY_ORGANIZATION_ID. The API rejects an organization that was not approved during device login.

AFFINITY_API_KEY remains available as an explicit environment override for non-interactive automation. Never pass a credential as a command argument.

Give an agent the complete operating contract before it acts:

affinity context
affinity context --json

The text form is a concise briefing. The JSON form also includes the generated operation catalog, policy classes, clinical invariants, authentication status, and the default budget of 100 API requests with a 30-second timeout per request. It does not require credentials.

Agent code mode

Evaluate one asynchronous JavaScript expression:

affinity eval 'await affinity.getAccount({})'

List every callable operation without making a request:

affinity operations
affinity operations --json

Pipe an expression over stdin and get compact JSON:

printf 'await affinity.listPractices({ limit: 10 })' | affinity eval - --json

For longer programs, default-export an AgentProgram from a TypeScript or JavaScript module:

import type { AgentProgram } from "@affinity-health/effect-sdk/code";

const program: AgentProgram = async ({ affinity, log }) => {
  log("Reading the first ten practices");
  return affinity.listPractices({ limit: 10 });
};

export default program;

Run it with Bun:

affinity run program.ts --json

The runner puts the program's result on stdout. log(...), diagnostics, and errors go to stderr, so agents can parse stdout without removing status messages.

Mutation policy

Code sessions are read-only by default. Test-mode mutations require --apply:

affinity run setup-practice.ts --apply

Order creation, cancellation, and signing-session operations also require --allow-clinical. Test mode must use synthetic patient and prescription data.

Live mutations require an exact second confirmation:

affinity run update-practice.ts \
  --mode live \
  --apply \
  --confirm-live LIVE

The mode flag governs the runner's policy. The API key and server remain responsible for authorization and the actual Test or Live data boundary.

The public contract includes previewOrder, createOrder, signOrder, submitOrder, and signAndSubmitOrder. Creation uses one patient and a prescriptions array. Use --apply --allow-clinical for order mutations. Fetch current versions and obtain the clinician's attestation before signing. See the headless workflow.

Each session permits 100 operations by default, with a 30-second timeout per operation. Use --max-requests and --timeout to lower or raise those limits.

The runner executes local code with the current operating-system user's permissions. It is not a sandbox. Run only code you trust. The runner removes AFFINITY_API_KEY from its process environment before evaluating agent code, but the injected affinity client remains authorized for the operations allowed by the session policy.

Await-friendly library

Applications can create the same client without the CLI:

import { createCodeSession } from "@affinity-health/effect-sdk/code";

const session = createCodeSession({
  apiKey: process.env.AFFINITY_API_KEY!,
  mode: "test",
  organizationId: "org_example",
});

try {
  const account = await session.affinity.getAccount({});
  console.log(account);
} finally {
  await session.dispose();
}

Use createCodeSession for bounded work because it exposes dispose(). createClient is available for process-lifetime clients.

Raw Effect operations

The package root exports the generated Effect operations directly:

import { Effect } from "effect";
import { layer, updatePatient } from "@affinity-health/effect-sdk";

const program = updatePatient({
  practiceId: "prac_example",
  patientId: "pat_example",
  name: {
    first: "Jane",
    last: "Doe",
  },
});

const patient = await Effect.runPromise(
  program.pipe(
    Effect.provide(
      layer({
        apiKey: process.env.AFFINITY_API_KEY!,
      }),
    ),
  ),
);

Operations have typed success, failure, and service requirements. Credentials resolve for each request, and service keys stay redacted inside the Effect configuration.

Configuration

The library accepts:

  • apiKey, required
  • apiBaseUrl, defaulting to https://api.joinaffinityai.com
  • apiVersion, defaulting to 2026-08-11
  • actor, an optional provider or user attribution

The CLI reads AFFINITY_API_KEY, AFFINITY_API_BASE_URL, AFFINITY_API_VERSION, AFFINITY_ACTOR_ID, AFFINITY_ACTOR_TYPE, and AFFINITY_MODE. Invocation flags take precedence over environment defaults for non-secret settings.

The SDK has no telemetry. The library supports runtimes with fetch, including Bun, Node.js 20 or newer, browsers, and workers. The CLI requires Bun. Service API keys must stay in trusted server-side code.

Regenerate

The repository commits the official Affinity OpenAPI document and generated TypeScript:

bun run generate
bun run check

Generation uses Distilled's OpenAPI-to-Smithy converter and Effect SDK generator. It also builds the agent operation registry from the same OpenAPI paths. Do not edit src/services or src/code/registry.ts by hand.