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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@fracture/parse

v0.3.1

Published

type safe parsing library

Readme

@fracture/parser Parser for TypeScript

A delarative, composable library of JSON compatible value parsers.

Install

npm install @fracture/parse

API

The gist: Parser<O,I> is a function that takes a type I in as its single argument and returns a Result<O,I>.

Result<O,I> is a union of Success<O>|Failure<I> which are container types that describe the success and failure branches of the Parser<O,I> logic.

This library was designed to be used with values returne from JSON.parse.

A basic JSON parser:

const parseJSON: Parser<any,any> = (input) => {
	try {
		return success(JSON.parse(input);
	} catch (error) {
		return failure(error.message, input);
	}
}

Parser<any,any> is not exactly useful when the goal is type safety. This library provides the building blocks to validate ad return JSON primitives and combinations of them.

Utility functios

A set of functions to simplify working with Result<O,I> types.

isSuccess

isSuccess is a guard function that refines a Result<O,I> to Success<O>.

const result = parseString(1);

if (isSuccess(result)) {
	const value = result.value; // value _is_ a `string`
}

isFailure

isFailure is the logical inverse of isSuccess and refines the Failure<I> branch of a Result<O,I>:

const result = parseString('maybe a string');

if (isFailure(result)) {
	throw new Error(result.message);
}

value

value unwraps the boxed value of Success<T>. Allows the shape of Success<T> to be opaque to the user of this api.

const result = parseString('maybe a string');
if (isSuccess(result)) {
	const theString = value(result);
}

success

Bulids a Success<T> result case:

const parseInteger: Parser<any, number> = (maybeNumber) => {
	const int = parseInt(maybeNumber);
	return int === maybeNumber
		? success(int)
		: failure(`${maybeNumber} not an int`, maybeNumber);
}

failure

Builds a Failure<T> result case:

const parsePositive: Parser<any, number> = (maybeNumber) => {
	return typeof maybeNumber === 'number' && maybeNumber > 0
		? success(maybeNumber)
		: failure(`${maybeNumber} not a posistive number`, maybeNumber);
}

Base Parsers

A set of parsers for non-container JSON literals that can be used to build more complex parsers.

  • parseString is Parser<any, string>
  • parseNumber is `Parser<any, number>
  • parseUndefined is Parser<any, undefined>
  • parseNull is Parser<any, null>
  • parseBoolean is Parser<any, boolean>
const result = parseString(("maybe a string": any));

if (isFailure(result)) {
	throw new Error(result.reason);
}

const strValue = value(result);

Parser Combinators

Combinators that combine parsers into more complex parsers.

parseObjectOf

parseObjectOf accepts key/value pairs of parsers and parses the key/value pairs of the value it receives.

const parsePerson = parseObjectOf({
	name: parseString,
	age: parseNumber,
	metInPerson: parseBoolean
});

const result = parsePerson({});

if (isFailure(result)) {
	throw new Error(result.reason);
}

const person = value(result);

// TypeScript knows person.name is a `string`.
console.log(`Hello ${person.name}`);
// TypeScript knows person.age is a `number`.
console.log(`Maybe born in`, (new Date()).getYear() - person.age);

parseArrayOf

For parsing values of type Array<T>.

Given any Parser<O,I>, succeeds when the input:

  1. is an Array
  2. each member of the Array succeeds the provider Parser<O,I>

parseArrayOf accepts a Parser<O,I> and returns a Parser<I, Array<O>>.

const parsePeople = parseArrayOf(parsePerson);

// Result<any, Array<{name: string, age: number, metInPerson: boolean}>>
const result = parsePeople(JSON.parse(someString));

parseIndexedObjectOf

For parsing values of type {[string]: T}.

Given a Parser<any, T> the returned parser succeeds when:

  1. The value is an indexed object
  2. Each member of the indexed object succeeds the provider Parser<any, T>
// An object that is an index of users, indexed by a string value
const parseUuser = parseObjectOf({username: parseString});
const parseUserIndex = parseIndexedObjectOf(parseUser);

parseExactly

Builds a parser that succeeds when the input is exactly equal to the provided value.

const parse = parseExactly('shipped');

const result = parse('pending');

if (isSuccess(result)) {
	const shipped: 'shipped' = result.value;
}

parseOneOf

Allows one of a list of parsers to succeed. Useful for parsing an enumeration of known values.

const parseStatus = parseOneOf(
	parseExactly('published'),
	parseExactly('draft')
);

// Result<any, 'published'|'draft'>
const result = parseStatus('other');

optional

Given any parser, returns a new parser that succeds when original parser succeeds or the value is null.

const parse = optional(parseString);

// Result<any, (null|string)>
const result = parse(null);

voidable

Given any parser, returns a new parser that succeeds when the original parser succeeds or the value is undefined.

const parse = voidable(parseString);

// Result<any, (undefined|string)>
const result = parse(undefined);

Complex Example


import {
	ParserType,
	parseObjectOf,
	parseArrayOf,
	parseString,
	parseExactly,
	optional,
	mapParser,
	success,
	isSuccess,
} from 'parser';

const parseAuthor = parseObjectOf({
	username: parseString,
	avatar: optional(parseString),
});

const parsePost = parseObjectOf(
	title: parseString,
	status: parseOneOf(
		parseExactly('published'),
		parseExactly('draft'),
	),
	author: parseAuthor,
	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
	publishedAt: mapParser(
		parseString,
		// assuming ISO8601 string
		string => success(new Date(string))
	),
);

/**
 * Expects JSON like:
 *
 * ```
 * {"posts": [...Post]}
 * ```
 */
const parseResponse = parseObjectOf({
	posts: parseArrayOf( parsePost )
})

/**
 * Chained with DOM fetch
 */
async function getPosts() {
	const response = await fetch('/api/site/awesome.blog/posts')
		.then(response => response.json())
		.then(parseResponse);

	/**
	 * Type guard to unwrap the parsed value
	 */
	if (isSuccess(response)) {
		// 🚀 The response was successfully parsed and is safely typed
		const postResponse = response.value;
		console.log(postResponse.posts);
		return;
	}
	throw new Error(response.reason);
}

// Use the types created by the parsers:

type Author = ParserType<typeof parseAuthor>;
type Post = ParserType<typeof parsePost>;

const author: Author = {
   username: 5, // 💥 Not a string!
};

const post: Post = {
	title: 'Hello World',
	status: 'other', // 💥 Not 'published' or 'draft'
	publishedAt: 1235500482, // 💥 Not a Date
};