@uxf/router 11.72.5 → 11.80.2

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.
Files changed (50) hide show
  1. package/README.md +69 -1
  2. package/package.json +1 -1
  3. package/{index.d.ts → router/index.d.ts} +1 -0
  4. package/{index.js → router/index.js} +1 -0
  5. package/router/merge-route-matchers.d.ts +2 -0
  6. package/router/merge-route-matchers.js +6 -0
  7. package/{router.d.ts → router/router.d.ts} +23 -3
  8. package/{router.js → router/router.js} +32 -2
  9. package/{router.test.js → router/router.test.js} +48 -1
  10. package/router/routes-check/__test__/app/app-directory/[param]/page.d.ts +0 -0
  11. package/router/routes-check/__test__/app/app-directory/[param]/page.js +1 -0
  12. package/router/routes-check/__test__/app/app-directory/page.d.ts +0 -0
  13. package/router/routes-check/__test__/app/app-directory/page.js +1 -0
  14. package/router/routes-check/__test__/pages/index.d.ts +0 -0
  15. package/router/routes-check/__test__/pages/index.js +1 -0
  16. package/router/routes-check/__test__/pages/product/[id].d.ts +0 -0
  17. package/router/routes-check/__test__/pages/product/[id].js +1 -0
  18. package/router/routes-check/__test__/pages/product/edit.d.ts +0 -0
  19. package/router/routes-check/__test__/pages/product/edit.js +1 -0
  20. package/router/routes-check/__test__/pages/product/index.d.ts +0 -0
  21. package/router/routes-check/__test__/pages/product/index.js +1 -0
  22. package/router/routes-check/__test__/pages/product-2/[id]/index.d.ts +0 -0
  23. package/router/routes-check/__test__/pages/product-2/[id]/index.js +1 -0
  24. /package/{helper.d.ts → router/helper.d.ts} +0 -0
  25. /package/{helper.js → router/helper.js} +0 -0
  26. /package/{helper.test.d.ts → router/helper.test.d.ts} +0 -0
  27. /package/{helper.test.js → router/helper.test.js} +0 -0
  28. /package/{router.test.d.ts → router/router.test.d.ts} +0 -0
  29. /package/{routes-check → router/routes-check}/routes-check.d.ts +0 -0
  30. /package/{routes-check → router/routes-check}/routes-check.js +0 -0
  31. /package/{routes-check → router/routes-check}/routes-check.test.d.ts +0 -0
  32. /package/{routes-check → router/routes-check}/routes-check.test.js +0 -0
  33. /package/{sitemap-generator.d.ts → router/sitemap-generator.d.ts} +0 -0
  34. /package/{sitemap-generator.js → router/sitemap-generator.js} +0 -0
  35. /package/{sitemap-generator.test.d.ts → router/sitemap-generator.test.d.ts} +0 -0
  36. /package/{sitemap-generator.test.js → router/sitemap-generator.test.js} +0 -0
  37. /package/{superstruct → router/superstruct}/array.d.ts +0 -0
  38. /package/{superstruct → router/superstruct}/array.js +0 -0
  39. /package/{superstruct → router/superstruct}/boolean.d.ts +0 -0
  40. /package/{superstruct → router/superstruct}/boolean.js +0 -0
  41. /package/{superstruct → router/superstruct}/index.d.ts +0 -0
  42. /package/{superstruct → router/superstruct}/index.js +0 -0
  43. /package/{superstruct → router/superstruct}/integer.d.ts +0 -0
  44. /package/{superstruct → router/superstruct}/integer.js +0 -0
  45. /package/{types.d.ts → router/types.d.ts} +0 -0
  46. /package/{types.js → router/types.js} +0 -0
  47. /package/{utils → router/utils}/object-to-xml.d.ts +0 -0
  48. /package/{utils → router/utils}/object-to-xml.js +0 -0
  49. /package/{utils → router/utils}/object-to-xml.test.d.ts +0 -0
  50. /package/{utils → router/utils}/object-to-xml.test.js +0 -0
package/README.md CHANGED
@@ -52,7 +52,7 @@ export default createRouter(
52
52
  // routes/index.ts
53
53
 
54
54
  import router from "./routes";
55
- import { UxfGetServerSideProps, UxfGetStaticProps } from "@uxf/router";
55
+ import { UxfGetServerSideProps, UxfGetStaticProps, ExtractSchema } from "@uxf/router";
56
56
  import { PreviewData as NextPreviewData } from "next/types";
57
57
 
58
58
  export const {
@@ -62,6 +62,8 @@ export const {
62
62
  useQueryParamsStatic
63
63
  } = router;
64
64
 
65
+ export type GetRouteSchema<K extends keyof RouteList> = ExtractSchema<RouteList[K]>;
66
+
65
67
  export type GetStaticProps<
66
68
  Route extends keyof RouteList,
67
69
  Props extends { [key: string]: any } = { [key: string]: any },
@@ -119,6 +121,72 @@ export default () => (
119
121
  )
120
122
  ```
121
123
 
124
+ ## RouteMatcher
125
+
126
+ ```tsx
127
+ import { createRouteMatcher } from "@app-routes";
128
+
129
+ // create active resolver
130
+ const routeMatcher = createRouteMatcher("admin/index", { param1: 123 });
131
+ // or
132
+ const routeMatcher = createRouteMatcher("admin/index");
133
+
134
+ // how to use in component
135
+
136
+ function MyComponent() {
137
+ const router = useRouter();
138
+ const isRouteActive = routeMatcher(router);
139
+
140
+ return <div>{isRouteActive ? "active" : "not active"}</div>;
141
+ }
142
+ ```
143
+
144
+ ### Custom route matchers
145
+
146
+ ```tsx
147
+ function createPathnameRouteMatcher(path: string): RouteMatcher {
148
+ return (router) => {
149
+ return router.pathname.startsWith(path);
150
+ }
151
+ }
152
+ ```
153
+
154
+ ```tsx
155
+ import { getCurrentRoute } from "@app-routes";
156
+
157
+ function createCustomRouteMatcher(): RouteMatcher {
158
+ return (router) => {
159
+ const { route, params } = getCurrentRoute(router);
160
+ if (route === "admin/index") {
161
+ // do something
162
+ } else if (route === "admin/form") {
163
+ // do something
164
+ }
165
+ }
166
+ }
167
+ ```
168
+
169
+ ### Merge multiple route matchers
170
+
171
+ ```tsx
172
+ import { mergeRouteMatchers } from "@uxf/router";
173
+
174
+ const routeMatcher = mergeRouteMatchers([
175
+ createRouteMatcher("admin/index"),
176
+ createRouteMatcher("admin/form"),
177
+ ]);
178
+ ```
179
+
180
+ ## Type-safe route params
181
+
182
+ ```tsx
183
+ import { GetRouteSchema } from "@app-routes";
184
+
185
+ const blogProps: GetRouteSchema<"blog/detail"> = {
186
+ id: 1,
187
+ }
188
+ ```
189
+
122
190
  ## GetStaticProps
123
191
 
124
192
  ```tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/router",
3
- "version": "11.72.5",
3
+ "version": "11.80.2",
4
4
  "description": "UXF Router",
5
5
  "author": "UXFans <dev@uxf.cz>",
6
6
  "homepage": "https://gitlab.com/uxf-npm/router#readme",
@@ -1,3 +1,4 @@
1
1
  export * from "./helper";
2
+ export * from "./merge-route-matchers";
2
3
  export * from "./router";
3
4
  export * from "./types";
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./helper"), exports);
18
+ __exportStar(require("./merge-route-matchers"), exports);
18
19
  __exportStar(require("./router"), exports);
19
20
  __exportStar(require("./types"), exports);
@@ -0,0 +1,2 @@
1
+ import { RouteMatcher } from "./router";
2
+ export declare function mergeRouteMatchers(routeMatchers: RouteMatcher[]): RouteMatcher;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeRouteMatchers = mergeRouteMatchers;
4
+ function mergeRouteMatchers(routeMatchers) {
5
+ return (router) => routeMatchers.some((routeMatcher) => routeMatcher(router));
6
+ }
@@ -1,8 +1,15 @@
1
1
  import { LinkProps } from "next/link";
2
+ import { NextRouter } from "next/router";
2
3
  import { Infer, Struct } from "superstruct";
3
4
  import { SitemapGeneratorOptions, SitemapGeneratorType, SitemapRouteResolvers } from "./sitemap-generator";
4
5
  import { QueryParams, RoutesDefinition } from "./types";
5
- type ExtractSchema<T> = T extends {
6
+ interface TransitionOptions {
7
+ shallow?: boolean;
8
+ locale?: string | false;
9
+ scroll?: boolean;
10
+ unstable_skipClientCache?: boolean;
11
+ }
12
+ export type ExtractSchema<T> = T extends {
6
13
  schema: Struct<infer U, any>;
7
14
  } ? U : null;
8
15
  type Options = {
@@ -14,20 +21,32 @@ type LocaleOptions<Locales extends string[]> = {
14
21
  export type FunctionParametersGenerator<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = {
15
22
  [K in keyof RouteList]: RouteList[K]["path"] extends string ? "schema" extends keyof RouteList[K] ? [K, ExtractSchema<RouteList[K]>, Options?] : [K, null?, Options?] : "schema" extends keyof RouteList[K] ? [K, ExtractSchema<RouteList[K]>, Options & LocaleOptions<Locales>] : [K, null, Options & LocaleOptions<Locales>];
16
23
  }[keyof RouteList];
24
+ export type FunctionParametersGeneratorWithPartialParams<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = {
25
+ [K in keyof RouteList]: "schema" extends keyof RouteList[K] ? [K, Partial<ExtractSchema<RouteList[K]>>?] : [K, null?];
26
+ }[keyof RouteList];
17
27
  type RouteFunction<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = (...args: FunctionParametersGenerator<Locales, RouteList>) => LinkProps["href"];
18
28
  type RouteToUrlFunction<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = (...args: FunctionParametersGenerator<Locales, RouteList>) => string;
19
29
  type QueryParamsResult<Nullable extends boolean, T extends keyof RouteList, Locales extends string[], RouteList extends RoutesDefinition<Locales>> = [
20
30
  Nullable extends true ? Infer<NonNullable<RouteList[T]["schema"]>> | null : Infer<NonNullable<RouteList[T]["schema"]>>,
21
31
  {
22
- push: (params: Infer<NonNullable<RouteList[T]["schema"]>>) => Promise<boolean>;
23
- replace: (params: Infer<NonNullable<RouteList[T]["schema"]>>) => Promise<boolean>;
32
+ push: (params: Infer<NonNullable<RouteList[T]["schema"]>>, options?: TransitionOptions) => Promise<boolean>;
33
+ replace: (params: Infer<NonNullable<RouteList[T]["schema"]>>, options?: TransitionOptions) => Promise<boolean>;
24
34
  }
25
35
  ];
36
+ type SimplyNextRouter = Pick<NextRouter, "pathname" | "query" | "isReady">;
37
+ export type RouteMatcher = (router: SimplyNextRouter) => boolean;
38
+ type CurrentRoute<RouteList extends RoutesDefinition<any>> = {
39
+ [K in keyof RouteList]: {
40
+ route: K;
41
+ params: "schema" extends keyof RouteList[K] ? ExtractSchema<RouteList[K]> | null : null;
42
+ };
43
+ }[keyof RouteList];
26
44
  type Router<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = {
27
45
  route: RouteFunction<Locales, RouteList>;
28
46
  routeToUrl: RouteToUrlFunction<Locales, RouteList>;
29
47
  createSitemapGenerator: (resolvers: SitemapRouteResolvers<Locales, RouteList>, options?: SitemapGeneratorOptions) => SitemapGeneratorType;
30
48
  routes: RouteList;
49
+ getCurrentRoute: (router: SimplyNextRouter) => CurrentRoute<RouteList>;
31
50
  useActiveRoute: () => ActiveRoute<Locales, RouteList>;
32
51
  /**
33
52
  * @deprecated use useQueryParamsStatic or useQueryParams instead
@@ -35,6 +54,7 @@ type Router<Locales extends string[], RouteList extends RoutesDefinition<Locales
35
54
  useQueryParamsDeprecated: <T extends keyof RouteList>() => QueryParams<RouteList, T>;
36
55
  useQueryParams: <T extends keyof RouteList>(routeName: T) => QueryParamsResult<false, T, Locales, RouteList>;
37
56
  useQueryParamsStatic: <T extends keyof RouteList>(routeName: T) => QueryParamsResult<true, T, Locales, RouteList>;
57
+ createRouteMatcher: (...args: FunctionParametersGeneratorWithPartialParams<Locales, RouteList>) => RouteMatcher;
38
58
  };
39
59
  type RouterOptions<L extends string[]> = {
40
60
  baseUrl?: string;
@@ -71,6 +71,17 @@ function createRouter(routes, routerOptions) {
71
71
  }
72
72
  return (options === null || options === void 0 ? void 0 : options.shouldBeAbsolute) ? `${routerOptions.baseUrl}${pathname}` : pathname;
73
73
  };
74
+ const getCurrentRoute = (router) => {
75
+ const activeRoute = Object.keys(routes).find((route) => typeof routes[route].path === "string"
76
+ ? routes[route].path === router.pathname
77
+ : Object.values(routes[route].path).includes(router.pathname));
78
+ if (!activeRoute) {
79
+ throw new Error("Active route not found.");
80
+ }
81
+ const schema = routes[activeRoute].schema;
82
+ const params = router.isReady && schema ? (0, superstruct_1.mask)(router.query, schema) : null;
83
+ return { route: activeRoute, params };
84
+ };
74
85
  return {
75
86
  route(...args) {
76
87
  var _a;
@@ -115,8 +126,8 @@ function createRouter(routes, routerOptions) {
115
126
  return [
116
127
  (0, superstruct_1.mask)(router.query, schema),
117
128
  {
118
- push: (params) => router.push(routeToUrl(routeName, params, {})),
119
- replace: (params) => router.replace(routeToUrl(routeName, params, {})),
129
+ push: (params, options) => router.push(routeToUrl(routeName, params, {}), undefined, options),
130
+ replace: (params, options) => router.replace(routeToUrl(routeName, params, {}), undefined, options),
120
131
  },
121
132
  ];
122
133
  },
@@ -134,5 +145,24 @@ function createRouter(routes, routerOptions) {
134
145
  },
135
146
  ];
136
147
  },
148
+ getCurrentRoute,
149
+ createRouteMatcher(...args) {
150
+ const [requiredRouteName, requiredParams] = args;
151
+ return (router) => {
152
+ const { route, params } = getCurrentRoute(router);
153
+ if (route !== requiredRouteName) {
154
+ return false;
155
+ }
156
+ if (!requiredParams || Object.keys(requiredParams).length === 0) {
157
+ return true;
158
+ }
159
+ for (const [paramName, paramValue] of Object.entries(requiredParams)) {
160
+ if ((params === null || params === void 0 ? void 0 : params[paramName]) !== paramValue) {
161
+ return false;
162
+ }
163
+ }
164
+ return true;
165
+ };
166
+ },
137
167
  };
138
168
  }
@@ -1,15 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const superstruct_1 = require("superstruct");
4
+ const merge_route_matchers_1 = require("./merge-route-matchers");
4
5
  const router_1 = require("./router");
5
6
  const superstruct_2 = require("./superstruct");
6
- const { routeToUrl } = (0, router_1.createRouter)({
7
+ const { routeToUrl, createRouteMatcher } = (0, router_1.createRouter)({
7
8
  index: {
8
9
  path: "/",
9
10
  schema: (0, superstruct_1.object)({
10
11
  queryParam: (0, superstruct_1.optional)((0, superstruct_1.string)()),
11
12
  }),
12
13
  },
14
+ manyParameters: {
15
+ path: "/many-parameters/[param1]/form/[param2]",
16
+ schema: (0, superstruct_1.object)({
17
+ param1: (0, superstruct_1.string)(),
18
+ param2: (0, superstruct_1.string)(),
19
+ queryParam1: (0, superstruct_1.optional)((0, superstruct_1.string)()),
20
+ queryParam2: (0, superstruct_1.optional)((0, superstruct_1.string)()),
21
+ }),
22
+ },
13
23
  catchAllSegments: {
14
24
  path: "/catch-all/[...pathParams]",
15
25
  schema: (0, superstruct_1.object)({
@@ -127,3 +137,40 @@ const DATA = [
127
137
  test("routeToUrl", () => {
128
138
  DATA.map(({ actual, expected }) => expect(actual).toBe(expected));
129
139
  });
140
+ test("create route matcher", () => {
141
+ expect(createRouteMatcher("manyParameters", { param1: "value-1" })({
142
+ isReady: true,
143
+ pathname: "/many-parameters/[param1]/form/[param2]",
144
+ query: { param1: "value-1", param2: "any", queryParam1: "any", queryParam2: "any" },
145
+ })).toBe(true);
146
+ expect(createRouteMatcher("manyParameters", { param1: "value-1" })({
147
+ isReady: true,
148
+ pathname: "/many-parameters/[param1]/form/[param2]",
149
+ query: { param1: "any", param2: "any" },
150
+ })).toBe(false);
151
+ expect(createRouteMatcher("manyParameters", { param1: "value-1", queryParam1: "query-1" })({
152
+ isReady: true,
153
+ pathname: "/many-parameters/[param1]/form/[param2]",
154
+ query: { param1: "value-1", param2: "any", queryParam1: "query-1" },
155
+ })).toBe(true);
156
+ });
157
+ test("merge route matchers", () => {
158
+ const routeMatcher1 = createRouteMatcher("manyParameters", { param1: "value-1", queryParam1: "query-1" });
159
+ const routeMatcher2 = createRouteMatcher("manyParameters", { param1: "value-2", queryParam1: "query-2" });
160
+ const routeMatcher = (0, merge_route_matchers_1.mergeRouteMatchers)([routeMatcher1, routeMatcher2]);
161
+ expect(routeMatcher({
162
+ pathname: "/many-parameters/[param1]/form/[param2]",
163
+ query: { param1: "value-1", queryParam1: "query-1", param2: "any" },
164
+ isReady: true,
165
+ })).toBe(true);
166
+ expect(routeMatcher({
167
+ pathname: "/many-parameters/[param1]/form/[param2]",
168
+ query: { param1: "value-2", queryParam1: "query-2", param2: "any" },
169
+ isReady: true,
170
+ })).toBe(true);
171
+ expect(routeMatcher({
172
+ pathname: "/many-parameters/[param1]/form/[param2]",
173
+ query: { param1: "value-3", queryParam1: "query-3", param2: "any" },
174
+ isReady: true,
175
+ })).toBe(false);
176
+ });
@@ -0,0 +1 @@
1
+ "use strict";
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+ "use strict";
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes