envil envil Docs

Effect and Results

Run app environments and handle typed, secret-safe failures.

appEnv.server and appEnv.client expose expected failures through Effect’s typed error channel.

import { Effect } from "effect";

const program = appEnv.server.pipe(
  Effect.catchTag("EnvValidationError", (error) =>
    Effect.logError(error.message),
  ),
);

Resolver errors remain precise and may be handled independently:

appEnv.server.pipe(
  Effect.catchTags({
    ResolverConfigurationError: handleResolverConfiguration,
    ResolverInitializationError: handleResolverInitialization,
    ResolverRequestFailed: handleResolverRequest,
    ResolverResponseDecodeFailed: handleResolverResponse,
  }),
);

Convert expected failures to a result

import { Effect } from "effect";
import { asResult } from "@ayronforge/envil";

const result = await Effect.runPromise(
  appEnv.server.pipe(asResult()),
);

if (!result.success) {
  console.error(result.error.message);
}

asResult() converts only typed failures. Defects and interruptions retain their normal Effect semantics.

Choose the runner at the boundary

const syncEnvironment = Effect.runSync(appEnv.server);
const asyncEnvironment = await Effect.runPromise(appEnv.server);

The same environment Effect supports either runner. An Effect containing an asynchronous resolver must be run asynchronously.