loveurl
v0.4.4
Published
A url builder and parser pack for handling url states in an easy way.(Beta Version)
Downloads
61
Maintainers
Readme
loveUrl
A URL builder and parser pack for handling URL states the easy way.
📦 Installation
Using npm:
npm install love-urlUsing yarn:
yarn add love-urlUsing pnpm:
pnpm add love-url⚡ TL;DR — Quick Usage
type MyParams = {
showDetails: boolean;
page: number;
tags: string[];
status: "draft" | "published" | "archived";
};
// Encode to URL
// existing params PRESERVED
// currentPath PRESERVED
const url = loveUrl<MyParams>({
showDetails: true,
page: 2,
tags: ["food", "travel"],
status: "published",
// This param will be removed
car: undefined,
});
// Pre-existing params ?name=bob&car=fiat%20multipla&page=1
/*
url = "/current-path?name=bob&showDetails=true&page=2&tags=_._food_._travel&status=published"
*/
// Encode to URL (existing params REMOVED)
const url = loveUrl<MyParams>(
{
showDetails: true,
page: 2,
tags: ["food", "travel"],
status: "published",
},
{
currentParams: null,
url: "/route-somewhere-else",
}
);
// Pre-existing params ?name=bob&page=1
/*
url = "/route-somewhere-else?showDetails=true&page=2&tags=_._food_._travel&status=published"
*/
// Decode from URL
const parsed = parseLoveUrl<MyParams>(
"?showDetails=true&page=2&tags=_._food_._travel&status=published"
// or window.location.search
);
/*
parsed = {
showDetails: true,
page: 2,
tags: ["food", "travel"],
status: "published"
}
*/🧠 Tip
- Arrays are encoded using a custom separator:
_._
This ensures:- Consistent decoding even with a single item (
tags=_._design→["design"]) - Reliable parsing when array items contain commas
- Consistent decoding even with a single item (
- Booleans and numbers are parsed and typed automatically
- Invalid values (e.g.,
status=broken) will be parsed asstringsunless custom validation is added
🚀 Motivation
loveUrl aims to simplify the common headaches when building and parsing URLs with parameters in modern JavaScript projects.
🔧 Key Use Cases
1. Building dynamic URLs that preserve client-side state
Imagine your user is at /currentPath/example and the current URL params are:
fileType=photo&selectedPeriod=weekly
Instead of manually constructing links, you can just use:
const ExampleComponent = () => (
<div>
{/* Renders: /currentPath/example?fileType=photo&selectedOption=option1&selectedPeriod=weekly */}
<a href={loveUrl({ selectedOption: "option1" })}>Option 1</a>
{/* Renders: /currentPath/example?fileType=photo&selectedOption=option2&selectedPeriod=weekly */}
<a href={loveUrl({ selectedOption: "option2" })}>Option 2</a>
{/* Renders: /currentPath/example?fileType=photo&selectedPeriod=weekly */}
<a href={loveUrl({ selectedOption: undefined })}>Clear</a>
</div>
);2. Building and fetching dynamic URLs for APIs
Building parameterized API URLs manually can get messy:
type DynamicDataOptions = {
startDate?: string;
endDate?: string;
format?: "photos" | "videos";
limit: number;
};
const fetchDynamicData = (params: DynamicDataOptions) => {
let dataUrl = "https://api.my-project/files/archive";
// Prevent undefined values from appearing in the query string
for (const key in params) {
if (params[key] === undefined) {
delete params[key];
}
}
const queryString = new URLSearchParams(params).toString();
if (queryString) dataUrl += `?${queryString}`;
const req = await fetch(dataUrl);
return await req.json();
};Or even worse:
const fetchDynamicData = ({
startDate,
endDate,
format,
limit,
}: DynamicDataOptions) => {
const req = await fetch(
`https://api.my-project/files/archive?startDate=${startDate}&endDate=${endDate}&format=${format}&limit=${limit}`
);
return await req.json();
};Imagine doing this with 12+ parameters 😭
✅ With loveUrl:
const fetchDynamicData = (params: DynamicDataOptions) => {
const req = await fetch(
loveUrl(params, { url: "https://api.my-project/files/archive" })
);
return await req.json();
};Clean. Type-safe. No string interpolation errors.
3. Parsing URL params without the chaos
Handling conversions manually can quickly get out of hand:
const ComponentThatUsesParams = () => {
const params = new URLSearchParams(window.location.search);
const myBoolean = params.get("myBoolean") === "true"; // string 'false' is truthy 😬
const limit = parseInt(params.get("limit"));
const percentage = parseFloat(params.get("percentage"));
let favoriteFoods = params.get("favoriteFoods");
if (favoriteFoods?.includes(",")) {
favoriteFoods = favoriteFoods.split(",");
}
return (
<div>
<h1>My Params as an object:</h1>
<code>
{JSON.stringify({
myBoolean,
limit,
percentage,
})}
</code>
</div>
);
};✅ With loveUrl:
const ComponentThatUsesParams = () => {
const { myBoolean, limit, percentage, favoriteFoods } = parseLoveUrl<{
myBoolean: boolean;
limit: number;
percentage: number;
favoriteFoods: string[];
}>(window.location.search);
return (
<div>
<h1>My Params as an object:</h1>
<code>
{JSON.stringify({
myBoolean,
limit,
percentage,
})}
</code>
</div>
);
};Type-safe, clean, and handles all conversions for you.
❤️ Why you'll love loveUrl
- Automatically ignores
undefinedvalues - Handles complex param types like arrays, numbers, and booleans
- Uses a custom array separator (
_._) for full consistency - Prevents messy string interpolation
- Decodes and encodes with full TypeScript support
- Deals with duplicate params gracefully
- Keeps your URLs and logic clean and reliable
