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

@texoport/effect-parser-combinators

v0.3.0

Published

Parse-only Effect combinators for text input.

Readme

@texoport/effect-parser-combinators

Parser combinators for Effect that work on strings and Stream<string> input. A parser is an Effect that reads from ParseState, so it composes with Effect.gen, preserves typed failures, and can wait for more input when a token crosses a chunk boundary.

This is for parsers that need to live in an Effect program or parse incrementally. If all you need is the fastest possible parser for one complete string, Parserator is a better fit.

Install

pnpm add @texoport/effect-parser-combinators effect

Parse a string

Use parser.pipe(parse(input)) at the boundary. parse returns the parser's ordinary typed Effect failure, with ParseError enriched with its one-based line and column. Use Effect.result only when the calling boundary needs failures as data.

import { Effect } from "effect"
import { digit, endOfInput, many, parse } from "@texoport/effect-parser-combinators"

const byte = Effect.gen(function* () {
  const digits = yield* many(digit, { atLeast: 1 })
  return Number(digits.join(""))
})

const parser = Effect.gen(function* () {
  const value = yield* byte
  yield* endOfInput
  return value
})

const value = Effect.runSync(parser.pipe(parse("101")))
// 101

Most programs should use the built-in lexical parsers instead of repeating a character parser. They do one buffered scan, which matters on long inputs.

import { Effect } from "effect"
import {
  endOfInput,
  parse,
  string,
  takeWhileChar1,
} from "@texoport/effect-parser-combinators"

const assignment = Effect.gen(function* () {
  yield* string("count=")
  const value = yield* takeWhileChar1(
    (char) => char >= "0" && char <= "9",
    "digit",
  )
  yield* endOfInput
  return Number(value)
})

Effect.runSync(assignment.pipe(parse("count=42")))

Parse a stream

parseStream pulls chunks only when a parser needs more input. string, regex, takeWhileChar, and takeUntilChar all handle a token split across chunks.

import { Effect, Stream } from "effect"
import {
  char,
  parseStream,
  takeUntilChar,
} from "@texoport/effect-parser-combinators"

const line = Effect.gen(function* () {
  const value = yield* takeUntilChar("\n")
  yield* char("\n")
  return value
})

const value = Effect.runSync(
  parseStream(Stream.fromIterable(["first", " line\nrest"]), line),
)
// "first line"

streamElements(input, element) runs an element parser repeatedly and releases consumed input after each successful element. The element parser must consume input.

Consumption and backtracking

Choice is ordered. or_(left, right) tries right only when left fails without consuming input. Wrap a branch in attempt when failure should rewind it.

import { Effect } from "effect"
import { attempt, char, or_ } from "@texoport/effect-parser-combinators"

const ab = Effect.gen(function* () {
  yield* char("a")
  yield* char("b")
  return "ab"
})

const ac = Effect.gen(function* () {
  yield* char("a")
  yield* char("c")
  return "ac"
})

const parser = or_(attempt(ab), ac)

many, manyUntil, and streamElements reject an element parser that succeeds without moving the cursor. That failure catches loops that would otherwise never end.

Core combinators

  • Character and token parsers: satisfy, char, digit, alphabet, anyChar, notChar, oneOfChars, string, anyOfStrings, regex.
  • Bulk scans: takeWhileChar, takeWhileChar1, takeUntilChar, whitespace, skipWhitespace.
  • Structure: many, manyUntil, count, between, sepBy, sepBy1, optional, lookAhead, notFollowedBy, or_, attempt.
  • Boundaries: endOfInput, parse, parseStream, streamElements.

takeUntilChar leaves its delimiter unread. Parse the delimiter next with char, as in the line example. If the delimiter never arrives, it consumes the rest of the input and returns a ParseError.

Errors

Expected input failures use ParseError, which records the absolute input position, the expected value, and the character found. parse also attaches a one-based line and column. An upstream stream failure becomes UpstreamError and keeps the original cause.

Bad combinator arguments, such as oneOfChars("") or count(digit, -1), return a failed Effect. The library does not throw configuration errors or turn parser contract failures into defects.

Development

pnpm --filter @texoport/effect-parser-combinators typecheck
pnpm --filter @texoport/effect-parser-combinators test
pnpm --filter @texoport/effect-parser-combinators bench