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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@innova2/url-builder

v3.1.0

Published

A lightweight library with many feature to easy build URLs

Downloads

304

Readme

Url-Builder

Coverage

A lightweight library with many features to easy build URLs

[!WARNING]
Breaking changes from 2.x to 3.x

  • UrlBuilder#addParam() has been removed. Use UrlBuilder#getPathParams().add() instead
  • UrlBuilder#addParams() has been removed. Use UrlBuilder#getPathParams().addAll() instead
  • UrlBuilder#addOrReplaceParam() has been removed. Use UrlBuilder#getPathParams().set() instead
  • UrlBuilder#addOrReplaceParams() has been removed. Use UrlBuilder#getPathParams().setAll() instead
  • UrlBuilder#findParams() has been removed. Use UrlBuilder#getPathParams().find() instead
  • UrlBuilder#addQueryParams() has been removed. Use UrlBuilder#getQueryParams().addAll() instead
  • UrlBuilder#addOrReplaceQueryParam() has been removed. Use UrlBuilder#getQueryParams().set() instead
  • UrlBuilder#addOrReplaceQueryParams() has been removed. Use UrlBuilder#getQueryParams().setAll() instead
  • UrlBuilder#findQueryParams() has been removed. Use UrlBuilder#getQueryParams().find() instead
  • UrlBuilder#getQueryString() has been removed. Use UrlBuilder#getQueryParams().toString() instead

:bookmark_tabs: Features

This library allows :

  • Create URLs most easly
  • Parse and decompose your URLs
  • Ride up in the URL tree
  • Make comparisons between URLs

:hammer_and_wrench: Installation

To import the library you just need to run this command :

npm install @innova2/url-builder

:memo: Usage

Create from existing URL

const url = UrlBuilder.createFromUrl('http://localhost:8080/users');
// or create new url with the constructor

Handle path

Add new path segment(s) and params

[!NOTE] All methods (except getBaseUrl) on PathParams object (by getPathParams()), return the current PathParams object and not the current UrlBuilder object [!NOTE] The add() and addAll() methods on PathParams object does not add the entry if the key already exists. Use set() or setAll() instead

const userId = '170b16cd-ad47-4c9c-86cf-7c83bd40d775';
url.addPath(':id/comments').getPathParams().add('id', userId);
// Or
url.addPath(':id/comments', { id: userId });

Add multiples parameters after adding path segment(s)

const userId = '170b16cd-ad47-4c9c-86cf-7c83bd40d775';
const commentId = '218dd1c4-0bb0-425a-be0b-85427304e100';
url.addPath(':userId/comments/:commentId').getPathParams().addAll({ userId, commentId });
// Or
url.addPath(':userId/comments/:commentId', { userId, commentId });

If you want to add or replace existing param(s), use instead :

const userId = '170b16cd-ad47-4c9c-86cf-7c83bd40d775';
const commentId = '218dd1c4-0bb0-425a-be0b-85427304e100';
url.addPath(':userId/comments/:commentId', { userId: 3, commentId: 1 });

// Without replacement :
url.getPathParams().add('userId', userId);
// Param 'userId' is always : 3

// With replacement :
url.getPathParams().set('userId', userId);
// Param 'userId' is now : 170b16cd-ad47-4c9c-86cf-7c83bd40d775


// Or with multiples parameters
// Without replacement :
url.getPathParams().addAll({ userId: 10, commentId: 5 });
// Param 'userId' is always : 170b16cd-ad47-4c9c-86cf-7c83bd40d775
// Param 'commentId' is always : 1

// With replacement :
url.getPathParams().setAll({ userId: 10, commentId: 5 });
// Param 'userId' is now : 10
// Param 'commentId' is now : 5

Retrieve params

const url = new UrlBuilder()
    .getPathParams().addAll({
      startDate: '1679737680454',
      endDate: '1679937680454',
    });

const params = url.getPathParams();
// params contains all path params as Map

const filteredParams = url.getPathParams().filter(([key, value]) => new Date(Number(value)).getDate() === 25);
// filteredParams contains a new Map only with param 'startDate'

Get the first path segment

const rowNum = 10;
const url = UrlBuilder.createFromUrl('http://localhost:8080/rows/:rowNum/cells').addParam('rowNum', rowNum);
url.getFirstPath(); // Output: 'rows'

Get the last path segment

url.getLastPath(); // Output: 'cells'

Delete some path params

const url = new UrlBuilder()
    .getPathParams().addAll({
      startDate: '1679737680454',
      endDate: '1679937680454',
    });

url.getPathParams().deleteBy(([key, value]) => new Date(Number(value)).getDate() === 25);
// PathParams no longer contains param 'endDate'

Handle query param

[!NOTE] All methods (except getBaseUrl) on QueryParams object (by getQueryParams()), return the current QueryParams object and not the current UrlBuilder object

[!NOTE] The add() and addAll() methods on QueryParams object does not add the entry if the key already exists. Use set() or setAll() instead Add new query param

const page = 2;
url.getQueryParams().add('page', page);

// or
url.addQueryParam('page', page);

Add multiples query params

const page = 2;
const order = 'DESC';
url.getQueryParams().addAll({ page, order });

If you want to add or replace existing query, use instead :

const page = 2;
const order = 'DESC';
url.getQueryParams().addAll({ page, order });

// Without replacement :
url.getQueryParams().add('page', 3);
// QueryParam 'page' is always : 2

// With replacement :
url.getQueryParams().set('page', 3);
// QueryParam 'page' is now : 3


// Or with multiples parameters
// Without replacement :
url.getQueryParams().addAll({ page: 4, order: 'ASC' });
// QueryParam 'page' is always : 3
// QueryParam 'order' is always : DESC

// With replacement :
url.getQueryParams().setAll({ page: 4, order: 'ASC' });
// QueryParam 'page' is now : 4
// QueryParam 'order' is now : ASC

Retrieve query params

const url = new UrlBuilder()
    .getQueryParams().addAll({
      style: 'dark',
      utm_source: 'Google',
      utm_medium: 'newsletter',
      utm_campaign: 'summer',
      isMobile: 1
    });

const queryParams = url.getQueryParams();
// queryParams contains all query params as Map

const filteredQueryParams = url.getQueryParams().filter(([key]) => key.startsWith('utm'));
// filteredQueryParams contains a new Map only with query params 'utm_source', 'utm_medium' and 'utm_campaign'

Delete some query params

const url = new UrlBuilder()
    .getQueryParams().addAll({
      style: 'dark',
      utm_source: 'Google',
      utm_medium: 'newsletter',
      utm_campaign: 'summer',
      isMobile: 1
    });

url.getQueryParams().deleteBy(([key]) => key.startsWith('utm'));
// QueryParams no longer contains query params 'utm_source', 'utm_medium' and 'utm_campaign'

Handle file

Parse file in url

// Consider file part of path segments
const url = UrlBuilder.createFromUrl('http://localhost/users/10.html');
url.getRelativePath();
// Output : /users/10.html
url.getPathSegments();
// Output : ['users', '10.html'];
url.getFile();
// Output : undefined

// Consider file dissociated of path segments
const url2 = UrlBuilder.createFromUrl('http://localhost/users/10.html', true);
url2.getRelativePath();
// Output : /users/10.html
url2.getPathSegments();
// Output : ['users'];
url2.getFile();
// Output : { name: '10', ext: 'html' }

Define file

url.setFile({ name: 'mycover', ext: 'webp' });
url.getFile();
// Output : { name: 'mycover', ext: 'webp' }

Define file from filename

url.setFilename('mycover.webp');
url.getFile();
// Output : { name: 'mycover', ext: 'webp' }

Handle fragment

Parse fragment with url

const url = UrlBuilder.createFromUrl('http://localhost/users?page=1#foo');
url.getRelativePath(false, true);
// Output : /users#foo
// The first boolean is "withQuery" and the seconde is "withFragment"
// With query params and fragment :
url.getRelativePath(true, true);
// Output : /users?page=1#foo

Define fragment without hash

url.setFragment('bar');

Retrieve fragment

const fragment = url.getFragment();
// Output : bar
url.getRelativePath(false, true);
// Output : /users#bar

Merge path and query params

It's possible to merge path and query params with another url

const url = UrlBuilder.createFromUrl('http://localhost:3000').addPath('groups');

const anotherUrl = new UrlBuilder()
    .addPath(':id/users', { id: 2 })
    .addQueryParam('page', 1)

url.mergePathWith(anotherUrl).toString() // Get 'http://localhost:3000/groups/2/users?page=1'

Note : This function merge only path, params and query params with current url.

Work with parent

Get parent URL easly. This function return a new instance of UrlBuilder

const url = UrlBuilder.createFromUrl('http://localhost:8080/orders/:orderId/products/:productId');
const parent = url.getParent(); // Get 'http://localhost:8080/orders/:orderId/products'

Or up to the specific level

url.getParent(3); // Get 'http://localhost:8080/orders'

Get relative path

Retrieve the relative path as string format

const postId = 'a937b39e-9664-404a-ac56-f3da2b83a951';
const url = UrlBuilder.createFromUrl('http://localhost:8080/posts/:id').addParam('id', postId);
url.getRelativePath(); // Output: '/posts/a937b39e-9664-404a-ac56-f3da2b83a951'

And with query params Don't forget to add 'true' parameter to allow query params conversion

url.addQueryParam('displaySimilar', true);
url.getRelativePath(); // Output: '/posts/a937b39e-9664-404a-ac56-f3da2b83a951'
url.getRelativePath(true); // Output: '/posts/a937b39e-9664-404a-ac56-f3da2b83a951?displaySimilar=true'

Get query params as string

Retrieve the query params as string format

const queryParams = UrlBuilder.createFromUrl('http://localhost:8080/vehicles').getQueryParams().setAll({
  page: 2,
  order: 'ASC',
});
queryParams.toString(); // Output: '?page=2&order=ASC'

Convert full URL to string

Retrieve the query params as string format

const name = 'url-builder';
const url = UrlBuilder.createFromUrl('https://github.com/InnovA2')
        .addPath(':name/pulls')
        .addParam('name', name);
url.toString(); // Output: 'https://github.com/InnovA2/url-builder/pulls'

:memo: Advanced

Compare URL to another

Compare the current URL to another URL (UrlBuilder instance)

const id = '434f65eb-4e5f-4b29-899c-b3e159fff61c';
const id2 = '3e972ca2-b422-4ac9-b793-e6f305c7bfb2';
const url = UrlBuilder.createFromUrl('http://localhost:8080/users/:id').addParam('id', id);
const url2 = UrlBuilder.createFromUrl('http://localhost:8080/users/:id').addParam('id', id);
const url3 = UrlBuilder.createFromUrl('http://localhost:8080/users/:id').addParam('id', id2);
url.compareTo(url2); // Output: true
url.compareTo(url3); // Output: false

Compare relative path to another by segment

Compare the path segments of the current URL to another relative path

const url: UrlBuilder = UrlBuilder.createFromUrl('/users/10/comments');
url.compareToPathBySegment('/users/10/comments') // Output: true
const url2: UrlBuilder = UrlBuilder.createFromUrl('/users/:id/comments');
url2.compareToPathBySegment('/users/10/comments') // Output: false
const url3: UrlBuilder = UrlBuilder.createFromUrl('/users/:id/comments').addParam('id', 10);
url3.compareToPathBySegment('/users/10/comments') // Output: true
// Or, validate unfilled params
const url4: UrlBuilder = UrlBuilder.createFromUrl('/users/:id/comments');
url4.compareToPathBySegment('/users/10/comments', true) // Output: true

Get path between two segments

const url = UrlBuilder.createFromUrl('http://localhost:8080/users/10/comments');
url.getBetween2Segments('users', 'comments'); // Output: 10

const url2 = UrlBuilder.createFromUrl('http://localhost:8080/users/10/comments/5');
url2.getBetween2Segments('users', '5'); // Output: 10/comments

:memo: Utils

Split path from string

Split path string by slash

UrlUtils.splitPath('/InnovA2/url-builder/pulls/'); // Output: ['InnovA2', 'url-builder', 'pulls']
// or if you have more slashes
UrlUtils.splitPath('/InnovA2///url-builder/pulls/'); // Output: ['InnovA2', 'url-builder', 'pulls']

Trim path from string

Trim path string by removing useless slashes

UrlUtils.trimPath('/InnovA2/url-builder/pulls/'); // Output: 'InnovA2/url-builder/pulls'
// or if you have more slashes
UrlUtils.trimPath('/InnovA2///url-builder/pulls/'); // Output: 'InnovA2/url-builder/pulls'

Parse filename

Parse filename to create file object containing 'name' and 'ext' (extension). Works with any extension (no verification).

UrlUtils.parseFile('image.png'); // Output: { name: 'image', ext: 'png' }

:gear: API

Types / Interfaces

type ParamType = string | number | boolean;
type ParamFindPredicate = (value: [string, ParamType], index: number, obj: [string, ParamType][]) => boolean;
interface FileInterface {
  name: string;
  ext: string;
}

UrlBuilder

static createFromUrl(baseUrl: string, isFile?: boolean): UrlBuilder;
copy(): UrlBuilder;
compareTo(url: UrlBuilder, relative?: boolean): boolean;
compareToPathBySegment(path: string, validateUnfilledParams?: boolean): boolean;
getScheme(): Scheme;
setScheme(scheme: Scheme): this;
getHost(): string;
setHost(host: string): this;
getPort(): number;
setPort(port: number): this;
getPathSegments(): string[];
setPathSegments(segments: string[], params?: Record<string, ParamType>): UrlBuilder;
addPath(path: string, params?: Record<string, ParamType>): UrlBuilder;
getPathParams(): PathParams;
setPathParams(params: PathParams): this;
getQueryParams(): QueryParams;
setQueryParams(query: QueryParams): this;
setFilename(filename: string): this;
setFile(file: IFile): this;
getFile(): IFile;
getFragment(): string;
setFragment(fragment: string): this;
mergePathWith(url: UrlBuilder): this;
getFirstPathSegment(): string;
getFirstPath(): string;
getLastPathSegment(): string;
getLastPath(): string;
getParent(n?: number): UrlBuilder;
getBetween2Segments(a: string, b: string): string | null;
getRelativePath(withQuery?: boolean, withFragment?: boolean): string;
toString(): string;

Note : Only the non-static getParent() method return new instance of UrlBuilder. Others update and return the current instance.

PathParams (extends Map<string, ParamType>)

constructor(baseUrl?: UrlBuilder, entries?: readonly (readonly [string, ParamType])[] | null);
getAll(): { [key: string]: ParamType };
add(key: string, value: ParamType): this;
addAll(params: Record<string, ParamType>): this;
setAll(params: Record<string, ParamType>): this;
deleteBy(predicate: ParamFindPredicate): this;
getBaseUrl(): UrlBuilder;
filter(predicate: ParamFindPredicate): PathParams;

QueryParams (extends Map<string, ParamType>)

constructor(baseUrl?: UrlBuilder, entries?: readonly (readonly [string, ParamType])[] | null);
getAll(): { [key: string]: ParamType };
add(key: string, value: ParamType): this;
addAll(params: Record<string, ParamType>): this;
setAll(params: Record<string, ParamType>): this;
deleteBy(predicate: ParamFindPredicate): this;
getBaseUrl(): UrlBuilder;
filter(predicate: ParamFindPredicate): QueryParams;
toString(): string;

UrlUtils (namespace)

splitPath(path: string): string[];
trimPath(path: string): string;
parseFile = (filename: string): FileInterface;

:balance_scale: Licence

MIT

:busts_in_silhouette: Authors

:handshake: Contributors

Do not hesitate to participate in the project! Contributors list will be displayed below.