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

@chriscdn/build-url

v2.1.0

Published

A small utility for building URLs.

Readme

@chriscdn/build-url

A small utility for building URLs.

Motivation

This package is a fork of @googlicius/build-url. Full credit to googlicius for the concept, source code, and original documentation. 👍

I forked this package for three reasons:

  • to provide an ESM build,
  • to fix this issue, and
  • to provide a named export.

Installation

npm install @chriscdn/build-url

Usage - buildUrl

The buildUrl(inputUrl?, options?) function builds and normalizes a URL. It accepts either a URL string followed by options, or an options object as the first argument.

Signature

buildUrl(inputUrl?: string, options?: UrlOptions): string;

buildUrl(options?: UrlOptions): string;

Options

type QueryParam = boolean | string | number | null | undefined;

type UrlOptions = {
  queryParams?: Record<string, QueryParam | QueryParam[]>;
  hash?: string;
  path?: string | null;
  appendPath?: string;
  returnAbsoluteUrl?: boolean;
};

| Option | Description | | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | queryParams | Sets, appends, or removes query parameters. A value sets the parameter, an array creates multiple values, and null or undefined removes the parameter. | | hash | Sets the URL fragment. | | path | Replaces the URL pathname. null clears the pathname. | | appendPath | Appends a path to the existing pathname and normalizes repeated slashes. | | returnAbsoluteUrl | Returns an absolute URL instead of a relative URL when the input URL is relative or omitted. |

Query parameters

A scalar value sets a query parameter:

import { buildUrl } from "@chriscdn/build-url";

buildUrl("/posts", {
  queryParams: {
    page: 2,
    published: true,
  },
});

// Output: /posts?page=2&published=true

An array creates multiple values for the same parameter:

buildUrl("/posts", {
  queryParams: {
    tag: ["typescript", "javascript"],
  },
});

// Output: /posts?tag=typescript&tag=javascript

null and undefined remove an existing parameter:

buildUrl("images?page=2&sort=title:asc", {
  queryParams: {
    page: null,
  },
});

// Output: /images?sort=title%3Aasc

When an array is supplied, null and undefined elements are ignored:

buildUrl("/posts", {
  queryParams: {
    tag: ["typescript", null, "javascript"],
  },
});

// Output: /posts?tag=typescript&tag=javascript

Path options

path replaces the existing pathname:

buildUrl("https://example.com/posts/123", {
  path: "/users/42",
});

// Output: https://example.com/users/42

Setting path to null clears the pathname:

buildUrl("https://example.com/posts/123", {
  path: null,
});

// Output: https://example.com

appendPath appends to the existing pathname:

buildUrl("/posts", {
  appendPath: "/123",
});

// Output: /posts/123

Repeated slashes are normalized when the path is processed:

buildUrl("/posts//", {
  appendPath: "//123//comments",
});

// Output: /posts/123/comments

Hash

Set a URL fragment with hash:

buildUrl("/posts/123", {
  hash: "comments",
});

// Output: /posts/123#comments

Absolute URLs

By default, relative URLs remain relative:

buildUrl("/posts", {
  queryParams: {
    page: 2,
  },
});

// Output: /posts?page=2

Set returnAbsoluteUrl to true to return an absolute URL.

In a browser, the current browser origin is used:

buildUrl("/posts", {
  returnAbsoluteUrl: true,
  queryParams: {
    page: 2,
  },
});

// Output: http://awesome-website.com/posts?page=2
// assuming window.location.origin is "http://awesome-website.com"

In Node.js, where there is no browser origin, http://example.com is used as the fallback origin. To produce a meaningful absolute URL in Node.js, provide an absolute input URL:

buildUrl("https://my-website.com/posts", {
  returnAbsoluteUrl: true,
  queryParams: {
    page: 2,
  },
});

// Output: https://my-website.com/posts?page=2

When returnAbsoluteUrl is true, a relative input URL is resolved against the current browser origin.

Options as the first argument

When there is no input URL, the options object can be passed directly:

buildUrl({
  queryParams: {
    sort: "title:asc",
  },
});

// Output: /?sort=title%3Aasc

This is equivalent to:

buildUrl(undefined, {
  queryParams: {
    sort: "title:asc",
  },
});

Usage - joinUrlPath

The joinUrlPath(segments, options?) function joins URL path segments into a normalized URL path.

It collapses consecutive slashes to a single slash, including repeated slashes within segments, while preserving the // in URL schemes such as https://.

By default, it preserves the leading slash of the first segment and the trailing slash of the last segment ("preserve"). Both can be forced on (true) or stripped (false) via the leading and trailing options.

Segments can be strings or numbers.

Signature

joinUrlPath(
  segments: readonly (string | number)[],
  options?: JoinUrlPathOptions,
): string;

Options

type SlashBehavior = boolean | "preserve";

type JoinUrlPathOptions = {
  leading?: SlashBehavior;
  trailing?: SlashBehavior;
};

| Option | Description | | ---------- | --------------------------------------------------------------------------------------------------------------------------------- | | leading | Controls the leading slash. "preserve" preserves the current behavior, true forces a leading slash, and false removes it. | | trailing | Controls the trailing slash. "preserve" preserves the current behavior, true forces a trailing slash, and false removes it. |

Examples

import { joinUrlPath } from "@chriscdn/build-url";

joinUrlPath(["api", "users", 42]);
// "api/users/42"

joinUrlPath(["/api////", "/users//", "/42////"]);
// "/api/users/42/"

joinUrlPath(["/api/", "users"], { trailing: true });
// "/api/users/"

joinUrlPath(["/api/", "users"], { leading: false });
// "api/users"

joinUrlPath(["https://example.com////", "/api//users"]);
// "https://example.com/api/users"

License

MIT