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

@structure-ai/config

v0.0.13

Published

Typed env + configuration management on Effect Config: layered providers, startup validation, redacted secrets.

Readme

@structure-ai/config

Typed environment + configuration management on Effect Config. Settings are defined once and yield both a validated, immutable config value and a rendered settings reference. Startup validation reports all issues together, then fails before the process accepts work.

Precedence (highest wins): explicit overrides → environment variables → JSON config file → dotenv file → code defaults.

Usage

import { load, Settings, toLayer } from "@structure-ai/config";
import { Context, Duration, Effect } from "effect";

const settings = Settings.struct({
  host: Settings.string("HOST", { default: "0.0.0.0" }),
  port: Settings.port("PORT", { description: "listen port" }),
  timeout: Settings.duration("TIMEOUT", { default: Duration.seconds(5) }),
  apiKey: Settings.secret("API_KEY"),
  otlpUrl: Settings.optional(Settings.url("OTLP_URL")),
});

const program = Effect.gen(function* () {
  const config = yield* load(settings, { dotEnvFile: ".env" });
  // config.port: number, config.apiKey: Redacted<string>, config.otlpUrl: Option<URL>
});

// Or as a layer: toLayer(SomeTag, settings, { configFile: "config.json" })
// Docs table for operators: Settings.renderDocs(settings)

Load options

| Option | Effect | | --- | --- | | overrides | Explicit values (e.g. parsed CLI flags). Highest precedence. | | env | Environment map used instead of process.env (same _ nesting delimiter: HTTP_PORT). Lets tests and CLIs load from a controlled map without mutating the process environment. | | blankMeansUnset | Default true: environment entries that are empty or whitespace-only count as unset, so PORT= falls back to the default and optional loads None. Applies to env and process.env, not to overrides, the config file, or the dotenv file. Set false to keep a literal empty string as a present value (an int then fails validation, an optional string loads Some("")). | | configFile | Versioned non-secret JSON file, below environment variables. | | dotEnvFile | Dotenv file below the config file. Opt-in, for local development. |

docker compose forwards an unset operator variable declared as VAR=${VAR:-} as VAR= (empty string); with the default blankMeansUnset that reaches settings as absent instead of Number("") === 0 or Some("").

// Production-shaped loading from a controlled map (no process.env mutation):
const config = yield* load(settings, { env: { PORT: "8080", API_KEY: "s3cret" } });

Exports

| Export | What it is | | --- | --- | | Settings.string/int/number/boolean/port/url/duration/logLevel/literal/secret | Leaf setting combinators carrying doc metadata. | | Settings.optional(setting) | Absent → Option.none() instead of an error. | | Settings.struct(fields) / Settings.nested(prefix, setting) | Composition; nesting prefixes env names (HTTP_PORT). | | Settings.renderDocs(setting) | Markdown table: name, type, required, default, secret, description. | | load(setting, options?) | Effect loading + validating; fails with ConfigLoadError. Options: overrides, env, blankMeansUnset, configFile, dotEnvFile. | | toLayer(tag, setting, options?) | The same as a Layer. | | withTestConfig(values)(effect) | Runs an effect against a fixed value map (tests). load(setting, { env }) is the production-shaped counterpart. | | ConfigLoadError | Tagged error with issues: ConfigIssue[], one per problem. | | parseDotEnv(content) | Minimal dotenv parser (used by dotEnvFile). Full .env support (cascade, expansion, multi-line quotes, edits, CLI) is @structure-ai/dotenv, which feeds load through the env option. |

Secrets (Settings.secret) load as Redacted<string> and never render in logs or errors.