@cloudflare/util-routes 5.2.36 → 5.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Change Log
2
2
 
3
+ ## 5.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3f146fca1c: Add useMatchRoute hook; fix optional parameter handling in useRoute
8
+
9
+ ## 5.3.0
10
+
11
+ ### Minor Changes
12
+
13
+ - a4dce672bb: Add support for optional params
14
+
3
15
  ## 5.2.36
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -30,3 +30,23 @@ const domainRoute = route`${domainsRoute}/${'domainName'}`
30
30
  // => /api/v4/accounts/123/domains/abc.com
31
31
  domainRoute.toUrl({ accountId: '123', domainName: 'abc.com' })
32
32
  ```
33
+
34
+ ### Optional Parameters
35
+
36
+ Parameters can be marked optional with a `?` suffix. TypeScript will make them optional in the `toUrl` signature:
37
+
38
+ ```typescript
39
+ const apiRoute = route`/api/${'filter?'}`
40
+
41
+ // filter is optional in toUrl
42
+ apiRoute.toUrl({}) // => /api
43
+ apiRoute.toUrl({ filter: 'active' }) // => /api/active
44
+
45
+ // Composing routes with optional params
46
+ const accountsRoute = route`/accounts/${'accountId'}`
47
+ const accountZonesRoute = route`${accountsRoute}/zones/${'filter?'}`
48
+
49
+ // TypeScript knows filter is optional
50
+ accountZonesRoute.toUrl({ accountId: '123' }) // => /accounts/123/zones
51
+ accountZonesRoute.toUrl({ accountId: '123', filter: 'active' }) // => /accounts/123/zones/active
52
+ ```
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './route';
2
2
  export * from './useRoute';
3
+ export * from './useMatchRoute';
package/dist/route.d.ts CHANGED
@@ -5,9 +5,7 @@ export declare class RoutePatternResult<Param extends string> {
5
5
  /**
6
6
  * Interperolate arguments into the route pattern
7
7
  */
8
- readonly toUrl: (args: {
9
- [K in Param]: string;
10
- }, options?: pathToRegExp.PathFunctionOptions) => string;
8
+ readonly toUrl: (args: RouteParams<Param>, options?: pathToRegExp.PathFunctionOptions) => string;
11
9
  readonly keys: Key[];
12
10
  readonly expression: RegExp;
13
11
  constructor(pattern: string);
@@ -20,7 +18,17 @@ export declare type RoutePatternResultFromParams<Params extends Array<string | R
20
18
  returnResult: RoutePatternResult<ValueOfArray<Result>>;
21
19
  recurse: RoutePatternResultFromParams<Tail<Params>, Prepend<ExtractParam<Head<Params>>, Result>>;
22
20
  }[Head<Params> extends never ? 'returnResult' : 'recurse'];
21
+ export declare type StripOptional<T extends string> = T extends `${infer Name}?` ? Name : T;
22
+ export declare type IsOptionalParam<T extends string> = T extends `${string}?` ? true : false;
23
23
  export declare type ExtractParam<T extends string | RoutePatternResult<string>> = T extends RoutePatternResult<infer S> ? S : T;
24
24
  export declare type ExtractRouteParamsInterface<T extends string | RoutePatternResult<string>> = {
25
25
  [K in ExtractParam<T>]: string | undefined;
26
26
  };
27
+ export declare type RequiredParams<Params extends string> = Params extends `${infer P}?` ? never : Params extends string ? Params : never;
28
+ export declare type OptionalParams<Params extends string> = Params extends `${infer P}?` ? P : never;
29
+ /** Maps route params to their resolved types: required params are `string`, optional params are `string | undefined`. */
30
+ export declare type RouteParams<Params extends string> = {
31
+ [K in RequiredParams<Params>]: string;
32
+ } & {
33
+ [K in OptionalParams<Params>]?: string;
34
+ };
@@ -0,0 +1,43 @@
1
+ import { ExtractParam, RouteParams, RoutePatternResult } from './route';
2
+ export declare function useMatchRoute<T extends RoutePatternResult<any>>(route: T, useMatch: (str: string) => any): PathMatch<RouteParams<ExtractParam<T>>> | null;
3
+ /**
4
+ * A PathMatch contains info about how a PathPattern matched on a URL pathname.
5
+ */
6
+ export interface PathMatch<Params extends {}> {
7
+ /**
8
+ * The names and values of dynamic parameters in the URL.
9
+ */
10
+ params: Params;
11
+ /**
12
+ * The portion of the URL pathname that was matched.
13
+ */
14
+ pathname: string;
15
+ /**
16
+ * The portion of the URL pathname that was matched before child routes.
17
+ */
18
+ pathnameBase: string;
19
+ /**
20
+ * The pattern that was used to match.
21
+ */
22
+ pattern: PathPattern;
23
+ }
24
+ /**
25
+ * A PathPattern is used to match on some portion of a URL pathname.
26
+ */
27
+ export interface PathPattern<Path extends string = string> {
28
+ /**
29
+ * A string to match against a URL pathname. May contain `:id`-style segments
30
+ * to indicate placeholders for dynamic parameters. May also end with `/*` to
31
+ * indicate matching the rest of the URL pathname.
32
+ */
33
+ path: Path;
34
+ /**
35
+ * Should be `true` if the static portions of the `path` should be matched in
36
+ * the same case.
37
+ */
38
+ caseSensitive?: boolean;
39
+ /**
40
+ * Should be `true` if this pattern should match the entire URL pathname.
41
+ */
42
+ end?: boolean;
43
+ }
@@ -1,4 +1,2 @@
1
- import { ExtractParam, RoutePatternResult } from './route';
2
- export declare function useRoute<T extends RoutePatternResult<any>>(route: T, useParams: () => any): {
3
- [K in ExtractParam<T>]: string;
4
- };
1
+ import { ExtractParam, RouteParams, RoutePatternResult } from './route';
2
+ export declare function useRoute<T extends RoutePatternResult<any>>(route: T, useParams: () => any): RouteParams<ExtractParam<T>>;
package/es/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './route';
2
- export * from './useRoute';
2
+ export * from './useRoute';
3
+ export * from './useMatchRoute';
package/es/route.js CHANGED
@@ -30,7 +30,9 @@ export function route(strings) {
30
30
  if (paramName instanceof RoutePatternResult) {
31
31
  result += paramName.pattern;
32
32
  } else if (typeof paramName === 'string') {
33
- result += ':' + paramName;
33
+ var isOptional = paramName.endsWith('?');
34
+ var cleanName = isOptional ? paramName.slice(0, -1) : paramName;
35
+ result += ':' + cleanName + (isOptional ? '?' : '');
34
36
  }
35
37
 
36
38
  return result;
@@ -0,0 +1,6 @@
1
+ export function useMatchRoute(route, useMatch) {
2
+ return useMatch(route.pattern);
3
+ }
4
+ /**
5
+ * A PathMatch contains info about how a PathPattern matched on a URL pathname.
6
+ */
package/es/useRoute.js CHANGED
@@ -3,9 +3,10 @@ export function useRoute(route, useParams) {
3
3
  var params = useParams();
4
4
 
5
5
  for (var {
6
- name
6
+ name,
7
+ optional
7
8
  } of route.keys) {
8
- if (typeof params[name] !== 'string') {
9
+ if (!optional && typeof params[name] !== 'string') {
9
10
  throw new Error("useRoute did not find the required parameters for this route: ".concat(route.pattern, ". Missing parameter: ").concat(name));
10
11
  }
11
12
 
package/lib/index.js CHANGED
@@ -28,4 +28,17 @@ Object.keys(_useRoute).forEach(function (key) {
28
28
  return _useRoute[key];
29
29
  }
30
30
  });
31
+ });
32
+
33
+ var _useMatchRoute = require("./useMatchRoute");
34
+
35
+ Object.keys(_useMatchRoute).forEach(function (key) {
36
+ if (key === "default" || key === "__esModule") return;
37
+ if (key in exports && exports[key] === _useMatchRoute[key]) return;
38
+ Object.defineProperty(exports, key, {
39
+ enumerable: true,
40
+ get: function get() {
41
+ return _useMatchRoute[key];
42
+ }
43
+ });
31
44
  });
package/lib/route.js CHANGED
@@ -50,7 +50,9 @@ function route(strings) {
50
50
  if (paramName instanceof RoutePatternResult) {
51
51
  result += paramName.pattern;
52
52
  } else if (typeof paramName === 'string') {
53
- result += ':' + paramName;
53
+ var isOptional = paramName.endsWith('?');
54
+ var cleanName = isOptional ? paramName.slice(0, -1) : paramName;
55
+ result += ':' + cleanName + (isOptional ? '?' : '');
54
56
  }
55
57
 
56
58
  return result;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useMatchRoute = useMatchRoute;
7
+
8
+ function useMatchRoute(route, useMatch) {
9
+ return useMatch(route.pattern);
10
+ }
11
+ /**
12
+ * A PathMatch contains info about how a PathPattern matched on a URL pathname.
13
+ */
package/lib/useRoute.js CHANGED
@@ -20,9 +20,11 @@ function useRoute(route, useParams) {
20
20
 
21
21
  try {
22
22
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
23
- var name = _step.value.name;
23
+ var _step$value = _step.value,
24
+ name = _step$value.name,
25
+ optional = _step$value.optional;
24
26
 
25
- if (typeof params[name] !== 'string') {
27
+ if (!optional && typeof params[name] !== 'string') {
26
28
  throw new Error("useRoute did not find the required parameters for this route: ".concat(route.pattern, ". Missing parameter: ").concat(name));
27
29
  }
28
30
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudflare/util-routes",
3
3
  "description": "Wraps path-to-regexp with a convenient, type-safe tagged template function",
4
- "version": "5.2.36",
4
+ "version": "5.4.0",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
7
7
  "author": "Frontend Team <frontend@cloudflare.com>",