@uxf/router 11.72.5 → 11.78.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 +56 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/merge-route-matchers.d.ts +2 -0
- package/merge-route-matchers.js +6 -0
- package/package.json +1 -1
- package/router.d.ts +14 -0
- package/router.js +30 -0
- package/router.test.js +48 -1
package/README.md
CHANGED
|
@@ -119,6 +119,62 @@ export default () => (
|
|
|
119
119
|
)
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
+
## RouteMatcher
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import { createRouteMatcher } from "@app-routes";
|
|
126
|
+
|
|
127
|
+
// create active resolver
|
|
128
|
+
const routeMatcher = createRouteMatcher("admin/index", { param1: 123 });
|
|
129
|
+
// or
|
|
130
|
+
const routeMatcher = createRouteMatcher("admin/index");
|
|
131
|
+
|
|
132
|
+
// how to use in component
|
|
133
|
+
|
|
134
|
+
function MyComponent() {
|
|
135
|
+
const router = useRouter();
|
|
136
|
+
const isRouteActive = routeMatcher(router);
|
|
137
|
+
|
|
138
|
+
return <div>{isRouteActive ? "active" : "not active"}</div>;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Custom route matchers
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
function createPathnameRouteMatcher(path: string): RouteMatcher {
|
|
146
|
+
return (router) => {
|
|
147
|
+
return router.pathname.startsWith(path);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { getCurrentRoute } from "@app-routes";
|
|
154
|
+
|
|
155
|
+
function createCustomRouteMatcher(): RouteMatcher {
|
|
156
|
+
return (router) => {
|
|
157
|
+
const { route, params } = getCurrentRoute(router);
|
|
158
|
+
if (route === "admin/index") {
|
|
159
|
+
// do something
|
|
160
|
+
} else if (route === "admin/form") {
|
|
161
|
+
// do something
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Merge multiple route matchers
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
import { mergeRouteMatchers } from "@uxf/router";
|
|
171
|
+
|
|
172
|
+
const routeMatcher = mergeRouteMatchers([
|
|
173
|
+
createRouteMatcher("admin/index"),
|
|
174
|
+
createRouteMatcher("admin/form"),
|
|
175
|
+
]);
|
|
176
|
+
```
|
|
177
|
+
|
|
122
178
|
## GetStaticProps
|
|
123
179
|
|
|
124
180
|
```tsx
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -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);
|
package/package.json
CHANGED
package/router.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
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";
|
|
@@ -14,6 +15,9 @@ type LocaleOptions<Locales extends string[]> = {
|
|
|
14
15
|
export type FunctionParametersGenerator<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = {
|
|
15
16
|
[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
17
|
}[keyof RouteList];
|
|
18
|
+
export type FunctionParametersGeneratorWithPartialParams<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = {
|
|
19
|
+
[K in keyof RouteList]: "schema" extends keyof RouteList[K] ? [K, Partial<ExtractSchema<RouteList[K]>>?] : [K, null?];
|
|
20
|
+
}[keyof RouteList];
|
|
17
21
|
type RouteFunction<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = (...args: FunctionParametersGenerator<Locales, RouteList>) => LinkProps["href"];
|
|
18
22
|
type RouteToUrlFunction<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = (...args: FunctionParametersGenerator<Locales, RouteList>) => string;
|
|
19
23
|
type QueryParamsResult<Nullable extends boolean, T extends keyof RouteList, Locales extends string[], RouteList extends RoutesDefinition<Locales>> = [
|
|
@@ -23,11 +27,20 @@ type QueryParamsResult<Nullable extends boolean, T extends keyof RouteList, Loca
|
|
|
23
27
|
replace: (params: Infer<NonNullable<RouteList[T]["schema"]>>) => Promise<boolean>;
|
|
24
28
|
}
|
|
25
29
|
];
|
|
30
|
+
type SimplyNextRouter = Pick<NextRouter, "pathname" | "query" | "isReady">;
|
|
31
|
+
export type RouteMatcher = (router: SimplyNextRouter) => boolean;
|
|
32
|
+
type CurrentRoute<RouteList extends RoutesDefinition<any>> = {
|
|
33
|
+
[K in keyof RouteList]: {
|
|
34
|
+
route: K;
|
|
35
|
+
params: "schema" extends keyof RouteList[K] ? ExtractSchema<RouteList[K]> | null : null;
|
|
36
|
+
};
|
|
37
|
+
}[keyof RouteList];
|
|
26
38
|
type Router<Locales extends string[], RouteList extends RoutesDefinition<Locales>> = {
|
|
27
39
|
route: RouteFunction<Locales, RouteList>;
|
|
28
40
|
routeToUrl: RouteToUrlFunction<Locales, RouteList>;
|
|
29
41
|
createSitemapGenerator: (resolvers: SitemapRouteResolvers<Locales, RouteList>, options?: SitemapGeneratorOptions) => SitemapGeneratorType;
|
|
30
42
|
routes: RouteList;
|
|
43
|
+
getCurrentRoute: (router: SimplyNextRouter) => CurrentRoute<RouteList>;
|
|
31
44
|
useActiveRoute: () => ActiveRoute<Locales, RouteList>;
|
|
32
45
|
/**
|
|
33
46
|
* @deprecated use useQueryParamsStatic or useQueryParams instead
|
|
@@ -35,6 +48,7 @@ type Router<Locales extends string[], RouteList extends RoutesDefinition<Locales
|
|
|
35
48
|
useQueryParamsDeprecated: <T extends keyof RouteList>() => QueryParams<RouteList, T>;
|
|
36
49
|
useQueryParams: <T extends keyof RouteList>(routeName: T) => QueryParamsResult<false, T, Locales, RouteList>;
|
|
37
50
|
useQueryParamsStatic: <T extends keyof RouteList>(routeName: T) => QueryParamsResult<true, T, Locales, RouteList>;
|
|
51
|
+
createRouteMatcher: (...args: FunctionParametersGeneratorWithPartialParams<Locales, RouteList>) => RouteMatcher;
|
|
38
52
|
};
|
|
39
53
|
type RouterOptions<L extends string[]> = {
|
|
40
54
|
baseUrl?: string;
|
package/router.js
CHANGED
|
@@ -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;
|
|
@@ -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
|
}
|
package/router.test.js
CHANGED
|
@@ -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
|
+
});
|