Profile
Back to NewsBack
GitHub Trending 4 min
Reader Mode
yielded-dev/auth: Composable authentication, sessions, and identity workflows for Effect.

yielded-dev/auth: Composable authentication, sessions, and identity workflows for Effect.

4 hours ago

Yielded Auth

npm CI MIT license

Documentation · Getting started · yielded.dev

Composable authentication, sessions, and identity workflows for Effect.

Define your contract with Schema, supply infrastructure with Layers, and call auth alongside your other Effects. The same contract connects your server to an Effect HttpClient service and Effect Atom queries and mutations.

Your application owns its accounts, identifiers, and authorization policy. Use managed auth tables, map an existing SQL schema, or implement storage services against another backend. The auth API stays the same when you change storage. Core has only Effect as a runtime peer; companion packages supply database, cryptography, and protocol adapters.

Start with Auth in an Effect application or compare database and backend choices. The four account apps show managed Drizzle, custom Drizzle, Effect SQL, and non-SQL persistence.

Install the beta release with Effect:

bun add @yielded/auth@beta effect

Prefer named namespace imports from @yielded/auth. Direct module paths such as @yielded/auth/AuthContract remain available; see the import guide.

One API, server and client

Define the shared contract in packages/domain/auth-contract.ts:

``ts [packages/domain/auth-contract.ts] import { Schema } from "effect"; import { AuthContract } from "@yielded/auth";

export const AuthApi = AuthContract.make("app/Auth", { claims: Schema.Struct({ displayName: Schema.String }), actions: (sessions) => ({ signIn: AuthContract.passwordSignIn(sessions) }), });

<!-- #endregion auth-contract -->

Bind the server implementation and mount its HTTP routes:

<!-- #region auth-server -->

ts [apps/server/auth.ts] import { Auth, Http, Password, Sessions } from "@yielded/auth";

import { AuthApi } from "@app/domain/auth-contract";

export const AppAuth = Auth.make(AuthApi, { sessions: Sessions.stateful({ maxAge: "8 hours", idleTimeout: "30 minutes" }), strategies: { password: Password.make() }, defaultStrategy: "password", });

export const AuthRoutes = Http.layer(AppAuth, { origin: "https://app.example.com" });

<!-- #endregion auth-server -->

The eight-hour lifetime and thirty-minute idle timeout are application policy. Supply your persistence and account Layers to AuthRoutes, then merge it with your router. For application routes that call auth, use the middleware shown in the router composition. Inside an existing Effect handler, call the service directly:

<!-- prettier-ignore -->

ts const auth = yield* AppAuth; const result = yield* auth.signIn({ email, password });
The request context supplies credentials and cookie delivery. auth.getSession(),
auth.requireSession(), and auth.signOut() use the same boundary. An
Authenticated sign-in result contains a session with typed claims.displayName.

Create the client and its atoms from the same contract:

<!-- #region auth-client -->

ts [apps/web/auth-client.ts] import { Atom as AuthAtom, Client } from "@yielded/auth";

import { AuthApi } from "@app/domain/auth-contract";

export const AppClient = Client.make(AuthApi, { baseUrl: "https://app.example.com" }); export const auth = AuthAtom.make(AppClient);

<!-- #endregion auth-client -->

Use auth.session, auth.signIn, and auth.signOut with ordinary @effect/atom-react hooks. Auth mutations refresh auth queries automatically; React renders and dispatches. Compose your own queries through the same client:

<!-- #region auth-query -->

ts [apps/web/member-name.ts] import { Effect } from "effect";

import { AppClient, auth } from "./auth-client";

export const memberName = auth.runtime.atom( Effect.gen(function* () { const client = yield* AppClient; const session = yield* client.auth.getSession();

return session?.claims.displayName ?? null; }), );

<!-- #endregion auth-query -->

Fetch is configured by default. To customize transport, compose AppClient.layer with your HttpClient Layer and pass { layer: ClientLive } to AuthAtom.make. See the client guide for React, shared invalidation, and standalone Effect calls.

Add passwords, passkeys, email or phone codes, two-factor authentication, and OAuth through strategies and their required Layers. OAuth can also retain encrypted provider grants for calling APIs after sign-in.

Start with the documentation and consumer examples. The public library lives in packages/auth; examples are leaf workspaces.

Development

Install Bun and Vite+, then run:

sh vp install vp run patch:tsgo vp run ready
``

The toolchain guide covers release setup and contributor rules. Shared versions live in the root catalog. Formatting, linting, strict TypeScript, package exports, dependency purity, tests, and builds use Vite+.

License

MIT

Chat with me