{"_id":"@carl.fyi/web","name":"@carl.fyi/web","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@carl.fyi/web","version":"0.1.0","description":"Handle the small, error-prone parts of the web: normalise URLs, validate UUIDs and parse pagination safely.","type":"module","sideEffects":false,"license":"MIT","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./http":{"types":"./dist/http.d.ts","import":"./dist/http.js"},"./identifiers":{"types":"./dist/identifiers.d.ts","import":"./dist/identifiers.js"},"./url":{"types":"./dist/url.d.ts","import":"./dist/url.js"}},"gitHead":"8395ae726af204ee2590ca681a8076b73a31a8e7","_id":"@carl.fyi/web@0.1.0","_nodeVersion":"26.7.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-2MmUAoZyIzpvkaSOFaULPN06RKbxmQcfROXvfGsJQCG23t75sNsq1bwy2iGtn1DDL/ZGMUsuqtRM4r/D8nNf8g==","shasum":"a51085c7fe0d577478002b16acb66fc641d0ae4d","tarball":"https://registry.npmjs.org/@carl.fyi/web/-/web-0.1.0.tgz","fileCount":19,"unpackedSize":33442,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIA6wvbQhP6cZ0kvg+yOiNTVn5xI2XEr3QNoO9VORVLBFAiEAsbCRIJQwd8wmiwtsLMcMD0V0TfMtkHBsCqpxveknuPs="}]},"_npmUser":{"name":"carlfairclough","email":"hi@carlfairclough.me"},"directories":{},"maintainers":[{"name":"carlfairclough","email":"hi@carlfairclough.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/web_0.1.0_1787903744678_0.9151018965495799"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-28T07:55:44.502Z","0.1.0":"2026-08-28T07:55:44.824Z","modified":"2026-08-28T07:55:45.060Z"},"maintainers":[{"name":"carlfairclough","email":"hi@carlfairclough.me"}],"description":"Handle the small, error-prone parts of the web: normalise URLs, validate UUIDs and parse pagination safely.","license":"MIT","readme":"<!-- Generated from package.json and src TSDoc by scripts/generate-tool-documentation.mjs. Do not edit by hand. -->\n\n# @carl.fyi/web\n\nHandle the small, error-prone parts of the web: normalise URLs, validate UUIDs and parse pagination safely.\n\n[Interactive documentation](https://tools.carl.fyi/packages/web)\n\n## Install\n\n```sh\nnpm install @carl.fyi/web\n```\n\n## Quick start\n\n```ts\nimport { normalizeHttpUrl, companyFromUrl } from \"@carl.fyi/web\";\n\nconst url = normalizeHttpUrl(\"www.example.com/docs#start\", { stripHash: true });\n// \"https://www.example.com/docs\"\n\ncompanyFromUrl(\"https://www.openai.com/research\"); // \"Openai\"\n```\n\n## Entry points\n\n| Import                      | Purpose                |\n| --------------------------- | ---------------------- |\n| `@carl.fyi/web`             | All public exports     |\n| `@carl.fyi/web/http`        | Focused subpath import |\n| `@carl.fyi/web/identifiers` | Focused subpath import |\n| `@carl.fyi/web/url`         | Focused subpath import |\n\nAll entry points are ESM, side-effect-free, and include TypeScript declarations.\n\n## Public API\n\nThis 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.\n\n| Export                    | Kind      | Import from                 | Description                                                              |\n| ------------------------- | --------- | --------------------------- | ------------------------------------------------------------------------ |\n| `pageToOffset`            | function  | `@carl.fyi/web/http`        | Public function exported by this package.                                |\n| `parseBooleanString`      | function  | `@carl.fyi/web/http`        | Public function exported by this package.                                |\n| `parsePagination`         | function  | `@carl.fyi/web/http`        | Parse page and limit query values and calculate their zero-based offset. |\n| `parsePositiveInteger`    | function  | `@carl.fyi/web/http`        | Public function exported by this package.                                |\n| `PositiveIntegerOptions`  | interface | `@carl.fyi/web/http`        | Public interface exported by this package.                               |\n| `isUuid`                  | function  | `@carl.fyi/web/identifiers` | Test whether a value is a structurally valid UUID.                       |\n| `normalizeUuid`           | function  | `@carl.fyi/web/identifiers` | Validate a UUID and normalise its hexadecimal letters to lowercase.      |\n| `uniqueValidIdentifiers`  | function  | `@carl.fyi/web/identifiers` | Validate, deduplicate, and preserve the first-seen order of identifiers. |\n| `UuidOptions`             | interface | `@carl.fyi/web/identifiers` | Public interface exported by this package.                               |\n| `companyFromUrl`          | function  | `@carl.fyi/web/url`         | Infer a human-friendly organisation label from a URL hostname.           |\n| `hostLabel`               | function  | `@carl.fyi/web/url`         | Return a display-oriented hostname without the common www. prefix.       |\n| `normalizeHttpUrl`        | function  | `@carl.fyi/web/url`         | Normalise an HTTP(S) URL and add a default protocol when needed.         |\n| `NormalizeHttpUrlOptions` | interface | `@carl.fyi/web/url`         | Public interface exported by this package.                               |\n\n# API reference\n\n## `@carl.fyi/web/url`\n\n### `normalizeHttpUrl`\n\n```ts\nnormalizeHttpUrl(input: string, options?: NormalizeHttpUrlOptions): string\n```\n\nNormalise an HTTP(S) URL and add a default protocol when needed.\n\nOnly HTTP and HTTPS inputs are accepted. The native `URL` serializer normalises casing, ports, and path syntax.\n\n| Parameter                            | Type                      | Description                                                        |\n| ------------------------------------ | ------------------------- | ------------------------------------------------------------------ |\n| `input`                              | `string`                  | Absolute or schemeless HTTP URL.                                   |\n| `options (optional)`                 | `NormalizeHttpUrlOptions` | Default protocol and fragment handling.                            |\n| `options.defaultProtocol (optional)` | `\"http:\" \\| \"https:\"`     | Protocol added when the input omits one. Default: `\"https:\"`.      |\n| `options.stripHash (optional)`       | `boolean`                 | Remove the URL fragment from the returned value. Default: `false`. |\n\n**Returns:** A fully qualified serialised URL.\n\n**Throws**\n\n- A `TypeError` for empty, malformed, non-HTTP, or hostless input.\n\n**Example**\n\n```ts\nimport { normalizeHttpUrl } from \"@carl.fyi/web\";\n\nconst url = normalizeHttpUrl(\"www.example.com/docs#start\", { stripHash: true });\n// \"https://www.example.com/docs\"\n```\n\n### `companyFromUrl`\n\n```ts\ncompanyFromUrl(input: string): string | null\n```\n\nInfer a human-friendly organisation label from a URL hostname.\n\nCommon country-code second-level suffixes are skipped before title-casing the registrable label. This is a display heuristic, not a public-suffix parser.\n\n| Parameter | Type     | Description                      |\n| --------- | -------- | -------------------------------- |\n| `input`   | `string` | Absolute or schemeless HTTP URL. |\n\n**Returns:** A title-cased organisation guess, or `null` for invalid input.\n\n**Example**\n\n```ts\nimport { companyFromUrl } from \"@carl.fyi/web\";\n\ncompanyFromUrl(\"https://www.openai.com/research\"); // \"Openai\"\n```\n\n## `@carl.fyi/web/http`\n\n### `parsePagination`\n\n```ts\nparsePagination(page: unknown, limit: unknown, options?: { defaultPage?: number; defaultLimit?: number; maxLimit?: number; }): { page: number; limit: number; offset: number; }\n```\n\nParse page and limit query values and calculate their zero-based offset.\n\nInvalid values fall back to configured defaults. A supplied limit above `maxLimit` also falls back rather than being clamped.\n\n| Parameter                         | Type                                                                                                                                                                                                                                                                       | Description                                      |\n| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |\n| `page`                            | `unknown`                                                                                                                                                                                                                                                                  | Candidate one-based page number.                 |\n| `limit`                           | `unknown`                                                                                                                                                                                                                                                                  | Candidate positive page size.                    |\n| `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.       |\n| `options.defaultPage (optional)`  | `number`                                                                                                                                                                                                                                                                   | Fallback when `page` is invalid. Default: `1`.   |\n| `options.defaultLimit (optional)` | `number`                                                                                                                                                                                                                                                                   | Fallback when `limit` is invalid. Default: `20`. |\n| `options.maxLimit (optional)`     | `number`                                                                                                                                                                                                                                                                   | Largest accepted limit. Default: `100`.          |\n\n**Returns:** Normalised `page`, `limit`, and calculated `offset` values.\n\n**Throws**\n\n- A `RangeError` if configured defaults are invalid or the offset exceeds the safe integer range.\n\n**Example**\n\n```ts\nimport { parsePagination } from \"@carl.fyi/web\";\n\nconst pagination = parsePagination(\"3\", \"25\", { maxLimit: 100 });\n// { page: 3, limit: 25, offset: 50 }\n```\n\n## `@carl.fyi/web/identifiers`\n\n### `isUuid`\n\n```ts\nisUuid(value: unknown, options?: UuidOptions): value is string\n```\n\nTest whether a value is a structurally valid UUID.\n\nValidation can be constrained to a version and the RFC variant while remaining case-insensitive.\n\n| Parameter                              | Type                                   | Description                                                |\n| -------------------------------------- | -------------------------------------- | ---------------------------------------------------------- |\n| `value`                                | `unknown`                              | Unknown value to test.                                     |\n| `options (optional)`                   | `UuidOptions`                          | Optional version and variant requirements.                 |\n| `options.version (optional)`           | `1 \\| 2 \\| 3 \\| 4 \\| 5 \\| 6 \\| 7 \\| 8` | Required UUID version nibble.                              |\n| `options.requireRfcVariant (optional)` | `boolean`                              | Require an RFC 4122/9562 variant nibble. Default: `false`. |\n\n**Returns:** `true` when the value is a matching UUID string.\n\n**Example**\n\n```ts\nimport { isUuid } from \"@carl.fyi/web\";\n\nisUuid(\"550e8400-e29b-41d4-a716-446655440000\", { version: 4, requireRfcVariant: true }); // true\n```\n\n### `normalizeUuid`\n\n```ts\nnormalizeUuid(value: string, options?: UuidOptions): string\n```\n\nValidate a UUID and normalise its hexadecimal letters to lowercase.\n\nThe UUID structure is preserved; only letter casing changes.\n\n| Parameter                              | Type                                   | Description                                                |\n| -------------------------------------- | -------------------------------------- | ---------------------------------------------------------- |\n| `value`                                | `string`                               | UUID string to validate and normalise.                     |\n| `options (optional)`                   | `UuidOptions`                          | Optional version and variant requirements.                 |\n| `options.version (optional)`           | `1 \\| 2 \\| 3 \\| 4 \\| 5 \\| 6 \\| 7 \\| 8` | Required UUID version nibble.                              |\n| `options.requireRfcVariant (optional)` | `boolean`                              | Require an RFC 4122/9562 variant nibble. Default: `false`. |\n\n**Returns:** The lowercase UUID.\n\n**Throws**\n\n- A `TypeError` when the value does not meet the requested constraints.\n\n**Example**\n\n```ts\nimport { normalizeUuid } from \"@carl.fyi/web\";\n\nconst id = normalizeUuid(\"550E8400-E29B-41D4-A716-446655440000\", { version: 4 });\n```\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_rev":"1-4d6b1db53ca77549819c66152eed1786"}