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

@kuroski/effect-svelte

v1.0.1

Published

Integration library for Effect with SvelteKit - seamless effect handling in SvelteKit remote functions

Downloads

11

Readme

effect-svelte

Integration library for Effect with SvelteKit. Run Effect programs in SvelteKit load functions and remote functions with automatic error handling, redirects, and form validation.

Installation

npm add effect-svelte
# or
bun add effect-svelte

Peer dependencies: effect >=3.19.15, svelte >=5, @sveltejs/kit >=2

Quick Start

1. Create a Runner

// src/lib/server/runtime.ts
import { Effect, Layer, ManagedRuntime } from "effect";
import { createRunner } from "effect-svelte";

const AppLayer = Layer.mergeAll(
  // your service layers
);

const RuntimeServer = ManagedRuntime.make(AppLayer);

export const remoteRunner = createRunner({
  runtime: RuntimeServer,
  before: () => Effect.log("Starting operation"),
  after: () => Effect.log("Operation completed"),
  onError: (err, isUnexpectedError) =>
    isUnexpectedError
      ? Effect.logError("Operation failed", err)
      : Effect.void,
});

2. Use in Load Functions

The runner works directly inside SvelteKit load functions. Call it with an operation name, your Effect program, and an optional error-mapping pipeline:

// src/routes/posts/+page.server.ts
import { Effect } from "effect";
import { httpErrorEffect } from "effect-svelte";
import { remoteRunner } from "$lib/server/runtime";

export async function load({ params }) {
  return remoteRunner(
    "load-posts",
    Effect.gen(function* () {
      const posts = yield* fetchPosts();

      if (posts.length === 0) {
        yield* httpErrorEffect(404, "NOT_FOUND", "No posts found");
      }

      return { posts };
    }),
  );
}
<!-- src/routes/posts/+page.svelte -->
<script lang="ts">
  let { data } = $props();
</script>

<ul>
  {#each data.posts as post (post.id)}
    <li>{post.title}</li>
  {/each}
</ul>

3. Use in Remote Functions

The same runner works with SvelteKit's experimental remote functions:

// src/routes/posts.remote.ts
import { Effect } from "effect";
import { query } from "$app/server";
import { remoteRunner } from "$lib/server/runtime";

export const getPosts = query(() =>
  remoteRunner(
    "get-posts",
    Effect.gen(function* () {
      yield* Effect.logInfo("Fetching posts");
      return { posts: [{ id: 1, title: "Hello" }] };
    }),
  ),
);
<!-- src/routes/+page.svelte -->
<script lang="ts">
  import { getPosts } from "./posts.remote.ts";
</script>

<svelte:boundary>
  {#snippet pending()}
    <p>loading...</p>
  {/snippet}

  {#snippet failed(error)}
    <span>Error: {error}</span>
  {/snippet}

  {@const { posts } = await getPosts()}
  <ul>
    {#each posts as post (post.id)}
      <li>{post.title}</li>
    {/each}
  </ul>
</svelte:boundary>

Error Handling

The library provides three tagged error types that map to SvelteKit's control flow:

import { Effect } from "effect";
import {
  SvelteKitRedirect,
  SvelteKitHttpError,
  SvelteKitInvalidError,
  redirectEffect,
  httpErrorEffect,
  invalidEffect,
} from "effect-svelte";

Effect.gen(function* () {
  // Redirect (throws SvelteKit redirect())
  yield* redirectEffect(303, "/login");
  // or: yield* Effect.fail(SvelteKitRedirect.make(303, "/login"));

  // HTTP error (throws SvelteKit error())
  yield* httpErrorEffect(404, "NOT_FOUND", "Resource not found");
  // or: yield* Effect.fail(SvelteKitHttpError.make(404, "NOT_FOUND", "Not found"));

  // Form validation error (throws SvelteKit invalid())
  yield* invalidEffect("email", "Invalid email format");
  // or: yield* Effect.fail(SvelteKitInvalidError.make({ email: "Invalid" }));
});

Pipeline for Error Mapping

Use the third argument of the runner to map domain errors to SvelteKit errors:

export const listProjects = remoteRunner(
  "listProjects",
  Effect.gen(function* () {
    const service = yield* ProjectService;
    return yield* service.all();
  }),
  (effect) =>
    effect.pipe(
      Effect.catchTags({
        ParseError: () =>
          httpErrorEffect(500, "PARSE_ERROR", "Unexpected data from the server"),
        ResponseError: () =>
          httpErrorEffect(500, "GENERIC_ERROR", "Unexpected server response"),
      }),
    ),
);

API Reference

createRunner(options)

Creates a runner function that executes Effect programs in a SvelteKit context.

Options:

| Option | Type | Description | |--------|------|-------------| | runtime | ManagedRuntime<R, never> | The Effect runtime to use | | before | () => Effect<void> | Runs before the effect | | after | (result: A) => Effect<void> | Runs after successful execution | | onError | (err, isUnexpectedError) => Effect<void> | Error handler. isUnexpectedError is true for 500+ errors and unrecognized failures, false for redirects, validation errors, and <500 HTTP errors |

Returns: Runner<R> - a function with signature:

(operationName: string, effect: Effect<A, E, R>, pipeline?: PipelineFn<R>) => Promise<A>

Execution order: beforeeffectpipelineonError (on failure) → after (on success) → withSpan(operationName)

Error Types

| Class | Converts to | Factory | |-------|-------------|---------| | SvelteKitRedirect | redirect(status, location) | SvelteKitRedirect.make(status, location) | | SvelteKitHttpError | error(status, body) | SvelteKitHttpError.make(status, code, message, details?) | | SvelteKitInvalidError | invalid(issues) | SvelteKitInvalidError.make(issues) |

Convenience Functions

| Function | Description | |----------|-------------| | redirectEffect(status, location) | Returns Effect.fail(SvelteKitRedirect.make(...)) | | httpErrorEffect(status, code, message, details?) | Returns Effect.fail(SvelteKitHttpError.make(...)) | | invalidEffect(issues) | Returns Effect.fail(SvelteKitInvalidError.make(...)) |

SvelteEffect.Code

Error code type: "GENERIC_ERROR" | "PARSE_ERROR" | "NOT_FOUND" | "UNAUTHORIZED"

License

MIT