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

partsing

v0.7.3

Published

decoder library for TypeScript

Readme

ParTSing

build status npm version npm version codecov

ParTSing is a decoder combinator library for TypeScript. You can use it to build parsers/decoders from text, tokens or really any input value.

If you want full control over what to decode your should start from partsing/core/decoder. It provides 3 types parameters

  • In for the input. Remember that you will need to decode one portion of your input at the time and your input probably needs to track somehow the current position.
  • Out it's the type of the value if successfully decoded.
  • Err it's the type of the failure returned when the parser fails.

The library provides two additional set of utility functions to decode string values (partsing/text) and native JS values (partsing/value).

Decoder Error

If you adopt the generic Decoder directly, you can define the shape of your error. The library provides a DecoderError type that should fit most decoding needs. The type of errors available are defined in partsing/error.

DecoderError provides a simple method to debug the result of the decoding (toString) but still leaves the flexibility to give granular control on the representation of the error.

Both [Text Decoding] and [Value Decoding] use DecodeError.

Text Decoding

To be able to keep track of the position of the decoding within a string, Text Decoding uses TextInput to track both the entire text input and the current index.

The decodeText function simplifies the inputs and outputs of decoding text. It takes a text decoder (Decoder<TextInput, T, DecoderError>) and return a function that takes a string input and returns a DecodeResult<string, T, string> (where input and error are of type string).

If you intend to write your own regular expressions decoder functions, consider using the y (sticky) flag. When used, there is no need to reallocate slices of the input string saving memory and CPU cycles. The sticky flag is not available for all implementations of JS.

Value Decoding

To be able to keep track of the position of the decoding within any value, Value Decoding uses ValueInput to track both the input value and the current position within it using a path. path is an array of either string (object field name) or number (array/tuple index position).

The decodeValue function simplifies the inputs and outputs of decoding values. It takes a value decoder (Decoder<ValueInput, T, DecoderError>) and return a function that takes any and returns a DecodeResult<any, T, string> (where input is of type any and error is of type string).

Example

A simple decoder combinator to parse color values from strings into class instances.

class RGB {
  constructor(readonly rgb: number) {}
  toString() {
    let s = this.rgb.toString(16)
    while (s.length < 6) s = `0${s}`
    return `#${s}`
  }
}

class Grey {
  constructor(readonly value: number) {}
  toString() {
    return `grey ${this.value}`
  }
}

class HSL {
  constructor(readonly hue: number, readonly saturation: number, readonly lightness: number) {}
  toString() {
    return `hsl(${this.hue},${this.saturation},${this.lightness})`
  }
}

type Color = RGB | Grey | HSL

// Hue in HSL is generally measured as an angle, not a ratio
const ratioDecoder = regexp(/0[.]\d+/y).map(Number)
const rgbDecoder = regexp(/[#]([0-9a-f]{6})/iy, 1)
  .map(v => parseInt(v, 16))
  .map(v => new RGB(v))
const greyDecoder = matchInsensitive('grey')
  .or(matchInsensitive('gray'))
  .skipNext(optionalWhitespace)
  .pickNext(ratioDecoder)
  .map(v => new Grey(v))
const hslDecoder = ratioDecoder
  .repeatWithSeparator(3, match(','))
  .map(v => new HSL(v[0], v[1], v[2]))
  .surroundedBy(matchInsensitive('hsl('), match(')'))

const colorTextDecoder = decodeText(
  // the `eoi` at the end, makes sure that there is nothing left to decode
  oneOf(rgbDecoder, greyDecoder, hslDecoder).skipNext(eoi)
)

// all results are wrapped in a DecodeSuccess
// colorTextDecoder('#003355')          == new RGB(0x003355)
// colorTextDecoder('gray 0.3')         == new Grey(0.3)
// colorTextDecoder('gray0.2')          == new Grey(0.2)
// colorTextDecoder('HSL(0.1,0.2,0.3)') == new HSL(0.1,0.2,0.3)

Another scenario where decoding comes in handy is to validate, type and transform payloads from JSON requests. You can decode a value (after being parsed by JSON.parse) into one of the Color types described above.

A few examples of valid JSON payloads:

"#003366"
{ "grey": 0.5 }
{ "kind": "hsl", "h": 0.2, "s": 0.5, "l": 0.8 }

Here is a colorValueDecoder definition that can deal with those cases:

const ratioValue = numberValue.test(v => v >= 0 && v <= 1, DecodeError.expectedWithinRange('0', '1'))

// reuse the rgbDecoder defined above to validate and trasform the string value into an RGB instance
// example: "#003366"
const rgbValue = stringValue.sub(rgbDecoder, input => ({ input, index: 0 }), v => v)

// example: { "grey": 0.5 }
const greyValue = objectValue(
    { grey: ratioValue },
    [] // the empty array means that no fields are optional
  ).map(v => new Grey(v.grey))

// example: { "kind": "hsl", "h": 0.2, "s": 0.5, "l": 0.8 }
const hslValue = objectValue(
    {
      kind: literalValue('hsl'),
      h: ratioValue,
      s: ratioValue,
      l: ratioValue
    },
    []
  ).map(v => new HSL(v.h, v.s, v.l))

const colorValueDecoder = decodeValue(
    oneOf(
      DecodeError.combine,
      rgbValue,
      greyValue,
      hslValue
    )
  )