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

effectify

v0.2.0

Published

Utility library that bridges Effect-ts with various utilities and projects, such as Astro!

Readme

effectify

A utility library that bridges Effect-ts with various utilities and projects, such as Astro!

Features

  • Effect-ts Integration - Convert Effect HTTP APIs to Astro API routes
  • Context Management - Seamless Astro context integration with Effect contexts
  • Web Handler Conversion - Built-in conversion utilities for Effect HTTP handlers
  • Scalar API Documentation - Integrated API documentation generation

Installation

pnpm add effectify

Usage

Undocumented Modules:

  • effectify/scalar - Custom version of the Scalar provided by Effect's HttpApi
  • effectify/scrypt - Node Scrypt Effect wrapper for password hashing

effectify/astro/* Modules

Utilities specific for working with Effect and Astro

effectify/astro/context

This module provides an AstroAPIContext export that can be used when working with Effect HTTP web handlers within an Astro environment.

Example

The example below shows how to access Astro locals from within en HttpApi handler

import { AstroAPIContext } from 'effectify/astro/context';

// Example of defining an Effect API and converting it to an Astro API route handler
const api = HttpApi.make('myApi').add(
	HttpApiGroup.make('group').add(HttpApiEndpoint.get('get', '/').addSuccess(Schema.String))
);

// Build the Effect API Handler (with Astro context)
const groupLive = HttpApiBuilder.group(api, 'group', (handlers) =>
	handlers.handle('get', () =>
		Effect.gen(function* () {
			const { locals } = yield* AstroAPIContext;
			console.log('Astro Locals:', locals); // Log the locals to verify access
			return 'Hello from Effect API!';
		})
	)
);

effectify/astro/HttApi

This module provides a Utility to wrap your Effect-based HttpApi into a Astro APIRoute

Example
// src/pages/myApi.ts
import { HttpApiToAstroRoute } from 'effectify/astro/HttApi';

// Example of defining an Effect API and converting it to an Astro API route handler
const api = HttpApi.make('myApi').add(
	HttpApiGroup.make('group').add(HttpApiEndpoint.get('get', '/').addSuccess(Schema.String))
);

// Build the Effect API Handler (with Astro context)
const groupLive = HttpApiBuilder.group(api, 'group', (handlers) =>
	handlers.handle('get', () =>
		Effect.gen(function* () {
			const { locals } = yield* AstroAPIContext;
			console.log('Astro Locals:', locals); // Log the locals to verify access
			return 'Hello from Effect API!';
		})
	)
);

// Create the Live Layer for the API
const MyApiLive = HttpApiBuilder.api(api).pipe(Layer.provide(groupLive));

// Convert the Effect API to an Astro API route handler
const ALL = HttpApiToAstroRoute(MyApiLive);

effectify/astro/integration

This module provides a defineIntegration utility for building Astro integrations with Effect-ts. The helper adds schema-validation for integration options and automatically wraps integration hooks to surface errors as EffectifyIntegrationHookError instances.

Features
  • Schema Validation - Validate integration options using Effect Schema at initialization time
  • Automatic Error Handling - All Effect-based hooks are wrapped to catch and re-throw errors with proper context
  • Type Safety - Full TypeScript support with inferred types from schemas
  • Effect Integration - Native Effect-ts patterns for hooks
Example
import { Effect, Schema } from 'effect';
import { defineIntegration, EffectifyIntegrationHookError } from 'effectify/astro/integration';

// Define an Astro integration with schema-validated options
export const myIntegration = defineIntegration({
	name: 'my-integration',
	schema: Schema.Struct({
		apiKey: Schema.String,
		enabled: Schema.optionalWith(Schema.Boolean, {
			default: () => true,
		}),
	}),
	setup: ({ name, options }) => ({
		'astro:config:setup': ({ logger }) =>
			Effect.gen(function* () {
				if (options.enabled) {
					logger.info(`${name} is enabled`);
				}
			}),
		'astro:config:done': ({ logger }) =>
			Effect.gen(function* () {
				logger.info(`Configuration complete for ${name}`);
			}),
	}),
});

// Use in astro.config.mjs
export default defineConfig({
	integrations: [
		myIntegration({
			apiKey: 'my-secret-key',
			enabled: true,
		}),
	],
});
Error Handling

The defineIntegration utility automatically wraps all hooks to catch errors. You can also explicitly handle errors within your hooks:

export const myIntegration = defineIntegration({
	name: 'my-integration',
	setup: ({ name, options }) => ({
		'astro:config:setup': ({ logger }) =>
			Effect.gen(function* () {
				// Your integration logic here
			}).pipe(
				Effect.catchAll((error) =>
					Effect.fail(
						new EffectifyIntegrationHookError({
							hook: 'astro:config:setup',
							message: 'Failed to setup integration',
							cause: error,
						})
					)
				)
			),
	}),
});

effectify/schemas

FunctionSchema / SyncFunctionSchema

These functions provide the ability to define custom functions within Effect Schema for both async and sync functions.

Example (FunctionSchema)

Creates a schema for functions with validated inputs and outputs. Similar to Zod's z.function().

The first param, is the args input, the second is the return. FunctionSchema will always return a async function. (promise-based)

import { FunctionSchema } from 'effectify/schemas';
import { Schema } from 'effect';

// Define your Schema
const LoginSchema = FunctionSchema(
	Schema.Struct({ username: Schema.String, password: Schema.String }),
	Schema.Boolean
);

// Example implementation function
const rawLoginFn = async (data: { username: string; password: string }) => {
	return data.username === 'admin' && data.password === '123';
};

// Create decoder
const decoder = Schema.decodeSync(LoginSchema)(rawLoginFn);

// Verify using implementation function internally
const result = await decoder({ username: 'admin', password: '123' });

console.log(result)
/* Console Output:
true
*/
Example (SyncFunctionSchema)

Similar to FunctionSchema but will always return a synchronous function.

import { SyncFunctionSchema } from 'effectify/schemas';
import { Schema } from 'effect';

// Define your Schema
const LoginSchema = SyncFunctionSchema(
	Schema.Struct({ username: Schema.String, password: Schema.String }),
	Schema.Boolean
);

// Example implementation function
const rawLoginFn = (data: { username: string; password: string }) => {
	return data.username === 'admin' && data.password === '123';
};

// Create decoder
const decoder = Schema.decodeSync(LoginSchema)(rawLoginFn);

// Verify using implementation function internally
const result = decoder({ username: 'admin', password: '123' });

console.log(result)
/* Console Output:
true
*/

effectify/static

makeStaticFileHttpApiRouter

Creates an HTTP API router that serves static files from a specified directory. The router can be configured to serve an index.html file for the root path and to set appropriate caching headers for files with hashed filenames.

// /src/index.ts
import { makeStaticFileHttpApiRouter } from 'effectify/static';

const TestStatic = makeStaticFileHttpApiRouter({
	htmlIndex: true, // (optional) Allows for serving index.html
	pathPrefix: '/assets' // (optional) Allows setting custom base path for served assets (leave blank for base route)
})(import.meta.dirname, 'static'); // Directory would be /src/static/

// If the source directory was /src/index.ts and the assets was located at /assets/
// then you would use (import.meta.dirname, '..', 'assets')

makeStaticFileMiddleware

The router above is simply a wrapper around this middleware, and has the same settings.

import { makeStaticFileMiddleware } from 'effectify/static';

const StaticMiddleware = makeStaticFileMiddleware()(import.meta.dirname, 'static');

effectify/webHandler

webHandlerToEffectHttpHandler

Converts a web handler function to an Effect HttpServerRequest handler.

import { webHandlerToEffectHttpHandler } from 'effectify/webHandler';

const mockWebHandler = async (request: Request) => {
	console.log('Received request:', request);
	return new Response('Hello from mock web handler!', { status: 200 });
};

const EffectHttpHandler = webHandlerToEffectHttpHandler(mockWebHandler);

EffectHttpHandlerToHttpApi

Utility function to convert a Effect-based web handler into a format that can be used with the HttpApiBuilder from Effect. This allows you to define your web handlers using Effect and then easily integrate them into an HTTP API.

// src/pages/[...api].ts
import { webHandlerToEffectHttpHandler, EffectHttpHandlerToHttpApi } from 'effectify/webHandler';

const mockWebHandler = async (request: Request) => {
	console.log('Received request:', request);
	return new Response('Hello from mock web handler!', { status: 200 });
};

const EffectHttpHandler = webHandlerToEffectHttpHandler(mockWebHandler);

const EffectHttpApiHandler = EffectHttpHandlerToHttpApi('*', EffectHttpHandler);

// Using a previous example to demonstrate possible usage
const ALL = HttpApiToAstroRoute(EffectHttpApiHandler);

Contributing

Contributions are welcome! Please follow the StudioCMS contribution guidelines.

License

MIT License

Links