@cookbook/urlkit 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # @cookbook/urlkit
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@cookbook/urlkit.svg)](https://www.npmjs.com/package/@cookbook/urlkit)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@cookbook/urlkit.svg)](https://www.npmjs.com/package/@cookbook/urlkit)
5
+ [![Bundle size](https://img.shields.io/bundlephobia/minzip/@cookbook/urlkit)](https://bundlephobia.com/package/@cookbook/urlkit)
6
+ [![CI](https://github.com/the-cookbook/urlkit/actions/workflows/ci.yml/badge.svg)](https://github.com/the-cookbook/urlkit/actions/workflows/ci.yml)
7
+
3
8
  Framework-agnostic typed URL contracts for parsing, validating, normalizing, matching, and building URL state.
4
9
 
5
10
  URLKit owns typed URL state: path params, search params, hash fragments, request parsing, URL normalization, matching, and href building. It sits between `@cookbook/pathkit` and higher-level router packages, but it does not define routes, route IDs, route trees, loaders, middleware, React hooks, components, or framework adapters.
@@ -176,7 +181,7 @@ ArticleUrl.build({ params: { slug: 'post-1' } });
176
181
  // ArticleUrl.build({ pathname: '/articles/post-1' });
177
182
  ```
178
183
 
179
- Path params are inferred from the pattern. Built-in `int` and `number` path constraints parse to numbers in standalone `url(...)` contracts.
184
+ Path params are inferred from the pattern. Built-in `int`, `decimal` and `range` path constraints parse to numbers in standalone `url(...)` contracts. PathKit does not expose a `{param:number}` built-in; use `{param:decimal}` for finite decimal path values.
180
185
 
181
186
  ```ts
182
187
  const UserUrl = url({ path: '/users/{id:int}' });
@@ -187,7 +192,7 @@ const user = UserUrl.parse('/users/42');
187
192
 
188
193
  ### Custom path constraints
189
194
 
190
- URLKit re-exports PathKit's `createConstraint` and provides global registration helpers for reusable path constraints. Custom constraints infer `string` params by default; built-in `int` and `number` still infer `number`.
195
+ URLKit re-exports PathKit's `createConstraint` and provides global registration helpers for reusable path constraints. Custom constraints infer `string` params by default; built-in `int`, `decimal` and `range` still infer `number`. When a PathKit constraint rejects a value, URLKit wraps it as `UrlKitError` with `code: 'invalid-param'` and preserves the original PathKit error in `error.cause`.
191
196
 
192
197
  ```ts
193
198
  import { createConstraint, registerPathConstraint, url } from '@cookbook/urlkit';
@@ -398,35 +403,32 @@ const Reports = search({
398
403
  });
399
404
  ```
400
405
 
401
- | Builder | Serialized format |
402
- | ---------------------------------------- | -------------------------------------- |
403
- | `date()` | Date-only `YYYY-MM-DD`. |
404
- | `dateTime()` | Strict UTC `YYYY-MM-DDTHH:mm:ss.sssZ`. |
405
- | `date({ format: 'unix-seconds' })` | Finite integer seconds. |
406
- | `date({ format: 'unix-ms' })` | Finite integer milliseconds. |
407
- | `date({ format: { parse, serialize } })` | Custom runtime date codec. |
406
+ | Builder | Serialized format |
407
+ | --------------------------------------------- | -------------------------------------- |
408
+ | `date()` | Date-only `YYYY-MM-DD`. |
409
+ | `dateTime()` | Strict UTC `YYYY-MM-DDTHH:mm:ss.sssZ`. |
410
+ | `date({ format: 'dd-MM-yyyy' })` | Strict custom date format string. |
411
+ | `dateTime({ format: 'dd-MM-yyyy HH:mm:ss' })` | Strict custom date-time format string. |
412
+ | `date({ format: { parse, serialize } })` | Custom runtime date codec. |
413
+ | `dateTime({ format: { parse, serialize } })` | Custom runtime date-time codec. |
414
+ | `date({ format: 'unix-seconds' })` | Finite integer seconds. |
415
+ | `date({ format: 'unix-ms' })` | Finite integer milliseconds. |
408
416
 
409
- Custom runtime date codecs are available only in runtime-builder schemas. Static date defaults use serialized values, not `Date` instances.
417
+ Custom date and date-time format strings are available only in runtime-builder schemas. Supported tokens are `yyyy`, `MM`, `dd`, `HH`, `mm`, `ss`, and `SSS`. Static date defaults use serialized values, not `Date` instances.
410
418
 
411
419
  ```ts
412
420
  const CustomDate = search({
413
- from: date({
414
- format: {
415
- parse(value) {
416
- const [day, month, year] = value.split('-');
417
- return new Date(Date.UTC(Number(year), Number(month) - 1, Number(day)));
418
- },
419
- serialize(value) {
420
- const day = String(value.getUTCDate()).padStart(2, '0');
421
- const month = String(value.getUTCMonth() + 1).padStart(2, '0');
422
- return `${day}-${month}-${value.getUTCFullYear()}`;
423
- },
424
- },
425
- }),
421
+ from: date({ format: 'dd-MM-yyyy' }),
422
+ at: dateTime({ format: 'dd-MM-yyyy HH:mm:ss' }).optional(),
426
423
  });
427
424
 
428
- CustomDate.build({ search: { from: new Date('2026-06-02T00:00:00.000Z') } });
429
- // '?from=02-06-2026'
425
+ CustomDate.build({
426
+ search: {
427
+ from: new Date('2026-06-02T00:00:00.000Z'),
428
+ at: new Date('2026-06-02T12:30:05.000Z'),
429
+ },
430
+ });
431
+ // '?from=02-06-2026&at=02-06-2026+12%3A30%3A05'
430
432
  ```
431
433
 
432
434
  ## Object search
@@ -634,16 +636,16 @@ try {
634
636
  }
635
637
  ```
636
638
 
637
- | Code | Meaning |
638
- | -------------------- | -------------------------------------------------------------------------- |
639
- | `invalid-url` | URL input could not be parsed as a URL. |
640
- | `path-mismatch` | URL pathname does not satisfy the path contract. |
641
- | `missing-param` | Required path param is missing. |
642
- | `invalid-param` | Path param is invalid. |
643
- | `missing-search` | Required search field is missing. |
644
- | `invalid-search` | Search value, unknown search behavior, or object search shape is invalid. |
645
- | `invalid-hash` | Hash value is missing or invalid. |
646
- | `invalid-descriptor` | Contract/schema/static descriptor is invalid at construction/compile time. |
639
+ | Code | Meaning |
640
+ | -------------------- | ------------------------------------------------------------------------------------------ |
641
+ | `invalid-url` | URL input could not be parsed as a URL. |
642
+ | `path-mismatch` | URL pathname does not satisfy the path contract. |
643
+ | `missing-param` | Required path param is missing. |
644
+ | `invalid-param` | Path param is invalid. Constraint failures preserve the original PathKit error in `cause`. |
645
+ | `missing-search` | Required search field is missing. |
646
+ | `invalid-search` | Search value, unknown search behavior, or object search shape is invalid. |
647
+ | `invalid-hash` | Hash value is missing or invalid. |
648
+ | `invalid-descriptor` | Contract/schema/static descriptor is invalid at construction/compile time. |
647
649
 
648
650
  ## TypeScript inference
649
651