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

url-craft

v1.0.0

Published

A powerful TypeScript library for URL parsing, manipulation, and building

Readme

url-craft

A powerful TypeScript library for URL parsing, manipulation, and building — with a handy CLI.

npm version license


Installation

npm install url-craft

For global CLI access:

npm install -g url-craft

Library Usage

import {
  parseURL,
  buildURL,
  setParams,
  removeParams,
  getParam,
  joinPath,
  normalizeURL,
  isValidURL,
} from "url-craft";

parseURL(url)

Parse a URL into structured components.

parseURL("https://example.com/path?foo=bar#section");
// {
//   protocol: "https",
//   hostname: "example.com",
//   pathname: "/path",
//   hash: "section",
//   params: { foo: "bar" },
//   ...
// }

buildURL(options)

Build a URL from parts.

buildURL({
  hostname: "api.example.com",
  pathname: "/v1/users",
  params: { page: "2", sort: "asc" },
});
// "https://api.example.com/v1/users?page=2&sort=asc"

setParams(url, params)

Add or update query parameters.

setParams("https://example.com?foo=old", { foo: "new", bar: "1" });
// "https://example.com?foo=new&bar=1"

removeParams(url, keys)

Remove one or more query parameters.

removeParams("https://example.com?a=1&b=2&c=3", ["a", "c"]);
// "https://example.com?b=2"

getParam(url, key)

Get the value of a single query parameter.

getParam("https://example.com?name=Alice", "name"); // "Alice"
getParam("https://example.com", "missing");          // null

joinPath(base, ...segments)

Join path segments onto a base URL.

joinPath("https://api.example.com/v1", "users", "42", "posts");
// "https://api.example.com/v1/users/42/posts"

setPathname(url, pathname)

Replace the pathname of a URL.

setPathname("https://example.com/old", "/new/path");
// "https://example.com/new/path"

setProtocol(url, protocol)

Change the protocol.

setProtocol("http://example.com", "https");
// "https://example.com/"

normalizeURL(url)

Sort query params, lowercase hostname, remove trailing slash.

normalizeURL("https://EXAMPLE.COM/path/?z=3&a=1");
// "https://example.com/path?a=1&z=3"

isValidURL(url)

Check whether a string is a valid URL.

isValidURL("https://example.com"); // true
isValidURL("not-a-url");           // false

stripQuery(url)

Remove query string and hash.

stripQuery("https://example.com/path?foo=bar#section");
// "https://example.com/path"

getDomain(url)

Extract the bare domain (without www).

getDomain("https://www.example.com/path"); // "example.com"

CLI Usage

url-craft <command> [options]

Commands

| Command | Description | |---|---| | parse <url> | Parse a URL into JSON components | | build <hostname> [--key val ...] | Build a URL from parts | | set-param <url> <key> <value> | Add or update a query parameter | | remove-param <url> <key> | Remove a query parameter | | get-param <url> <key> | Get a query parameter value | | validate <url> | Check if a URL is valid | | normalize <url> | Normalize a URL | | domain <url> | Extract the domain | | strip-query <url> | Remove query string and hash | | join <base> <...segments> | Join path segments | | net -url ip=<host:port> [-p <url>] | Start a static file server |

net — Static File Server

Serve HTML, CSS, JS and any static assets from a local directory, bound to a specific IP and port. Optionally accept traffic from a public custom domain.

# Serve current directory on 192.168.1.49:300
url-craft net -url ip="192.168.1.49:300"

# Serve current directory and accept public domain requests
url-craft net -url ip="192.168.1.49:300" -p http://www.customdomain.com

# Serve a specific folder
url-craft net -url ip="0.0.0.0:8080" --root ./dist -p https://www.mysite.com

# Quiet mode (no request logs)
url-craft net -url ip="192.168.1.49:300" --quiet

Flags

| Flag | Description | |---|---| | -url ip="host:port" | (required) IP and port to bind the server to | | -p <url> | Public domain to serve (enables host-header filtering) | | --root <dir> | Directory to serve files from (default: current directory) | | --quiet / -q | Disable per-request logging |

How -p works

When you pass -p http://www.customdomain.com, the server:

  1. Accepts HTTP requests arriving on the bound IP:port as normal
  2. Filters incoming Host headers — only serves requests matching your domain (plus localhost)
  3. Returns 421 Misdirected Request for any other host header

To make your custom domain point to this server, set an A record in your DNS to your machine's public IP address.

Examples

url-craft parse "https://example.com/path?foo=bar#section"

url-craft set-param "https://example.com?page=1" page 2

url-craft validate "not-a-url"

url-craft join "https://api.example.com/v1" users 42 posts

url-craft normalize "https://EXAMPLE.COM/path/?z=3&a=1"

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build
npm run build

License

MIT