@carl.fyi/web
v0.1.0
Published
Handle the small, error-prone parts of the web: normalise URLs, validate UUIDs and parse pagination safely.
Readme
@carl.fyi/web
Handle the small, error-prone parts of the web: normalise URLs, validate UUIDs and parse pagination safely.
Install
npm install @carl.fyi/webQuick start
import { normalizeHttpUrl, companyFromUrl } from "@carl.fyi/web";
const url = normalizeHttpUrl("www.example.com/docs#start", { stripHash: true });
// "https://www.example.com/docs"
companyFromUrl("https://www.openai.com/research"); // "Openai"Entry points
| Import | Purpose |
| --------------------------- | ---------------------- |
| @carl.fyi/web | All public exports |
| @carl.fyi/web/http | Focused subpath import |
| @carl.fyi/web/identifiers | Focused subpath import |
| @carl.fyi/web/url | Focused subpath import |
All entry points are ESM, side-effect-free, and include TypeScript declarations.
Public API
This is the complete export inventory. The detailed reference below mirrors the APIs demonstrated on the documentation website; its signatures, descriptions, defaults, errors, and examples are compiled from the package source.
| Export | Kind | Import from | Description |
| ------------------------- | --------- | --------------------------- | ------------------------------------------------------------------------ |
| pageToOffset | function | @carl.fyi/web/http | Public function exported by this package. |
| parseBooleanString | function | @carl.fyi/web/http | Public function exported by this package. |
| parsePagination | function | @carl.fyi/web/http | Parse page and limit query values and calculate their zero-based offset. |
| parsePositiveInteger | function | @carl.fyi/web/http | Public function exported by this package. |
| PositiveIntegerOptions | interface | @carl.fyi/web/http | Public interface exported by this package. |
| isUuid | function | @carl.fyi/web/identifiers | Test whether a value is a structurally valid UUID. |
| normalizeUuid | function | @carl.fyi/web/identifiers | Validate a UUID and normalise its hexadecimal letters to lowercase. |
| uniqueValidIdentifiers | function | @carl.fyi/web/identifiers | Validate, deduplicate, and preserve the first-seen order of identifiers. |
| UuidOptions | interface | @carl.fyi/web/identifiers | Public interface exported by this package. |
| companyFromUrl | function | @carl.fyi/web/url | Infer a human-friendly organisation label from a URL hostname. |
| hostLabel | function | @carl.fyi/web/url | Return a display-oriented hostname without the common www. prefix. |
| normalizeHttpUrl | function | @carl.fyi/web/url | Normalise an HTTP(S) URL and add a default protocol when needed. |
| NormalizeHttpUrlOptions | interface | @carl.fyi/web/url | Public interface exported by this package. |
API reference
@carl.fyi/web/url
normalizeHttpUrl
normalizeHttpUrl(input: string, options?: NormalizeHttpUrlOptions): stringNormalise an HTTP(S) URL and add a default protocol when needed.
Only HTTP and HTTPS inputs are accepted. The native URL serializer normalises casing, ports, and path syntax.
| Parameter | Type | Description |
| ------------------------------------ | ------------------------- | ------------------------------------------------------------------ |
| input | string | Absolute or schemeless HTTP URL. |
| options (optional) | NormalizeHttpUrlOptions | Default protocol and fragment handling. |
| options.defaultProtocol (optional) | "http:" \| "https:" | Protocol added when the input omits one. Default: "https:". |
| options.stripHash (optional) | boolean | Remove the URL fragment from the returned value. Default: false. |
Returns: A fully qualified serialised URL.
Throws
- A
TypeErrorfor empty, malformed, non-HTTP, or hostless input.
Example
import { normalizeHttpUrl } from "@carl.fyi/web";
const url = normalizeHttpUrl("www.example.com/docs#start", { stripHash: true });
// "https://www.example.com/docs"companyFromUrl
companyFromUrl(input: string): string | nullInfer a human-friendly organisation label from a URL hostname.
Common country-code second-level suffixes are skipped before title-casing the registrable label. This is a display heuristic, not a public-suffix parser.
| Parameter | Type | Description |
| --------- | -------- | -------------------------------- |
| input | string | Absolute or schemeless HTTP URL. |
Returns: A title-cased organisation guess, or null for invalid input.
Example
import { companyFromUrl } from "@carl.fyi/web";
companyFromUrl("https://www.openai.com/research"); // "Openai"@carl.fyi/web/http
parsePagination
parsePagination(page: unknown, limit: unknown, options?: { defaultPage?: number; defaultLimit?: number; maxLimit?: number; }): { page: number; limit: number; offset: number; }Parse page and limit query values and calculate their zero-based offset.
Invalid values fall back to configured defaults. A supplied limit above maxLimit also falls back rather than being clamped.
| Parameter | Type | Description |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| page | unknown | Candidate one-based page number. |
| limit | unknown | Candidate positive page size. |
| options (optional) | { /** Fallback when `page` is invalid. @defaultValue `1` */ defaultPage?: number; /** Fallback when `limit` is invalid. @defaultValue `20` */ defaultLimit?: number; /** Largest accepted limit. @defaultValue `100` */ maxLimit?: number; } | Pagination defaults and maximum page size. |
| options.defaultPage (optional) | number | Fallback when page is invalid. Default: 1. |
| options.defaultLimit (optional) | number | Fallback when limit is invalid. Default: 20. |
| options.maxLimit (optional) | number | Largest accepted limit. Default: 100. |
Returns: Normalised page, limit, and calculated offset values.
Throws
- A
RangeErrorif configured defaults are invalid or the offset exceeds the safe integer range.
Example
import { parsePagination } from "@carl.fyi/web";
const pagination = parsePagination("3", "25", { maxLimit: 100 });
// { page: 3, limit: 25, offset: 50 }@carl.fyi/web/identifiers
isUuid
isUuid(value: unknown, options?: UuidOptions): value is stringTest whether a value is a structurally valid UUID.
Validation can be constrained to a version and the RFC variant while remaining case-insensitive.
| Parameter | Type | Description |
| -------------------------------------- | -------------------------------------- | ---------------------------------------------------------- |
| value | unknown | Unknown value to test. |
| options (optional) | UuidOptions | Optional version and variant requirements. |
| options.version (optional) | 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 | Required UUID version nibble. |
| options.requireRfcVariant (optional) | boolean | Require an RFC 4122/9562 variant nibble. Default: false. |
Returns: true when the value is a matching UUID string.
Example
import { isUuid } from "@carl.fyi/web";
isUuid("550e8400-e29b-41d4-a716-446655440000", { version: 4, requireRfcVariant: true }); // truenormalizeUuid
normalizeUuid(value: string, options?: UuidOptions): stringValidate a UUID and normalise its hexadecimal letters to lowercase.
The UUID structure is preserved; only letter casing changes.
| Parameter | Type | Description |
| -------------------------------------- | -------------------------------------- | ---------------------------------------------------------- |
| value | string | UUID string to validate and normalise. |
| options (optional) | UuidOptions | Optional version and variant requirements. |
| options.version (optional) | 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 | Required UUID version nibble. |
| options.requireRfcVariant (optional) | boolean | Require an RFC 4122/9562 variant nibble. Default: false. |
Returns: The lowercase UUID.
Throws
- A
TypeErrorwhen the value does not meet the requested constraints.
Example
import { normalizeUuid } from "@carl.fyi/web";
const id = normalizeUuid("550E8400-E29B-41D4-A716-446655440000", { version: 4 });