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

urlargs

v1.14.0

Published

Utility for parsing URL query parameters with types.

Readme

urlargs

Type-safe utility for parsing URL query parameters.

Quick start

import { UrlArgs } from 'urlargs';

const args = new UrlArgs( {
  enabled: false,
  count:   10,
  name:    'test',
} );

// 🌐 ?count=20&enabled=true&name=foo
args.values.count    // → 20
args.values.enabled  // → true
args.values.name     // → 'foo'

args.values is fully typed and frozen. Mutations are caught at compile time and runtime.

Argument types

Use the u namespace to declare anything more complex than a plain primitive default:

import { UrlArgs, u } from 'urlargs';

const args = new UrlArgs( {
  count:    10,                                 // number
  name:     'test',                             // string
  enabled:  true,                               // boolean
  tags:     u.array( [ 'a', 'b' ] ),            // string[] (default [ 'a', 'b' ])
  scores:   u.array( u.number() ),              // number[] (default [])
  port:     u.optional( u.number() ),           // number | undefined
  bio:      u.nullable( u.string() ),           // string | null
  theme:    u.oneof( [ 'light', 'dark' ] ),     // 'light' | 'dark'
  config:   u.json<Config>( defaultConfig ),    // Config
} );

Primitives

Plain values become typed arguments with that value as the default:

new UrlArgs( {
  count:   10,       // number
  name:    'test',   // string
  enabled: true,     // boolean
} );

Booleans

These URL values are accepted:

| True | False | |------|-------| | 🟢 ?enabled=true | 🔴 ?enabled=false | | 🟢 ?enabled=TRUE | 🔴 ?enabled=FALSE | | 🟢 ?enabled=1 | 🔴 ?enabled=0 | | 🟢 ?enabled | | | 🟢 ?enabled= | |

Arrays

u.array has two forms. Pass a default array and the element type is inferred:

new UrlArgs( {
  tags:    u.array( [ 'a', 'b' ] ),     // string[]
  scores:  u.array( [ 1, 2, 3 ] ),      // number[]
  flags:   u.array( [ true, false ] ),  // boolean[]
} );

For an empty array, pass an explicit element type:

new UrlArgs( {
  tags:    u.array( u.string() ),    // string[]
  scores:  u.array( u.number() ),    // number[]
  flags:   u.array( u.boolean() ),   // boolean[]
} );

By default, arrays accept both repeated keys and comma-separated values:

🌐 ?tags=a&tags=b           → [ 'a', 'b' ]
🌐 ?tags=a,b,c              → [ 'a', 'b', 'c' ]
🌐 ?tags=a,b&tags=c,d       → [ 'a', 'b', 'c', 'd' ]

See array modes to change this behavior.

Optional and nullable

u.optional and u.nullable wrap any other type:

new UrlArgs( {
  port:    u.optional( u.number() ),               // number | undefined
  bio:     u.nullable( u.string() ),               // string | null
  tags:    u.optional( u.array( u.string() ) ),    // string[] | undefined
  theme:   u.nullable( u.oneof( [ 'a', 'b' ] ) ),  // 'a' | 'b' | null
} );

Both default to the nullish value, but you can pass an explicit default:

u.optional( u.number(), 10 )    // defaults to 10
u.nullable( u.string(), 'hi' )  // defaults to 'hi'

The URL strings undefined and null are recognized as sentinels:

🌐 ?port=undefined  →  undefined
🌐 ?bio=null        →  null

One of (enum)

Restrict an argument to a fixed set:

new UrlArgs( {
  theme:    u.oneof( [ 'light', 'dark', 'auto' ] ),  // 'light' | 'dark' | 'auto'
  fontSize: u.oneof( [ 12, 14, 16, 18 ] ),           // 12 | 14 | 16 | 18
  mode:     u.oneof( [ 'a', 'b', 'c' ], 'b' ),       // default to 'b'
} );

The first option is the default unless an explicit one is provided.

JSON

For arbitrary JSON values, use u.json with a default:

type Config = { w: number; h: number; info: { on: boolean } };

new UrlArgs( {
  config: u.json<Config>( { w: 100, h: 100, info: { on: false } } ),
  items:  u.json( [ 1, 2, 3 ] ),
} );

// 🌐 ?config={"w":200,"h":300,"info":{"on":true}}&items=[4,5,6]

The type is inferred from the default, or can be specified with a generic.

To validate the parsed shape at runtime, pass a predicate:

const isConfig = ( v: unknown ): boolean =>
  typeof v === 'object' && v !== null
    && typeof ( v as Config ).w === 'number'
    && typeof ( v as Config ).h === 'number';

u.json<Config>( defaultConfig, isConfig );

If the predicate returns false, the default is used and a warning is logged (or an error is thrown in strict mode).

Array modes

The default array mode, auto, accepts both repeated keys and comma-separated values. To opt into a specific behavior, pass arrayMode:

new UrlArgs( defaults, { arrayMode: 'comma' } );

| Mode | Behavior | |------|----------| | auto (default) | Splits commas and collects repeated keys | | comma | Splits commas only | | repeated | Collects repeated keys only |

In comma and auto modes, commas inside values can be escaped with a backslash:

🌐 ?tags=a,b\,c  →  [ 'a', 'b,c' ]

Re-parsing

Pass an explicit query string in the constructor, or call parse() later:

const args = new UrlArgs( { count: 10 } );

args.parse( '?count=42' );
args.values.count  // → 42

This is useful for tests, single-page apps that respond to URL changes, and server-side rendering.

When no string is provided, parse() reads from window.location.search (or an empty string if window isn't defined).

Options

new UrlArgs( defaults, {
  search:    '?count=10',  // explicit query string
  arrayMode: 'auto',       // 'auto' | 'comma' | 'repeated'
  strict:    false,        // throw on invalid input instead of warning
} );

Documenting arguments

Print a styled table of arguments and their values to the console:

args.describe( {
  count:   'The number of items to display',
  enabled: 'Whether the items are enabled',
  name:    'The name of the items',
} );

Values that differ from their defaults are highlighted.

console output

Use describeAll() to log every argument, including those without descriptions.

Validation

When a URL value is invalid for its declared type, urlargs logs a warning and falls back to the default:

const args = new UrlArgs( { count: 10 } );
// 🌐 ?count=banana
args.values.count  // → 10 (warning logged)

In strict mode, invalid values throw instead:

new UrlArgs( { count: 10 }, { strict: true } );
// 🌐 ?count=banana   →  throws

Defaults that aren't supported throw at construction time, regardless of mode:

new UrlArgs( { foo: undefined } );  // throws — use u.optional()
new UrlArgs( { foo: null } );       // throws — use u.nullable()