revine 1.3.0 → 1.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/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/components/MiddlewareGuard.d.ts +10 -0
- package/dist/components/MiddlewareGuard.d.ts.map +1 -0
- package/dist/components/MiddlewareGuard.js +28 -0
- package/dist/runtime/bundler/revinePlugin.d.ts.map +1 -1
- package/dist/runtime/bundler/revinePlugin.js +51 -4
- package/dist/runtime/middleware.d.ts +24 -0
- package/dist/runtime/middleware.d.ts.map +1 -0
- package/dist/runtime/middleware.js +7 -0
- package/package.json +1 -1
- package/src/client.ts +2 -0
- package/src/components/MiddlewareGuard.tsx +39 -0
- package/src/runtime/bundler/revinePlugin.ts +51 -4
- package/src/runtime/middleware.ts +29 -0
package/dist/client.d.ts
CHANGED
|
@@ -8,5 +8,7 @@ export type { NavLinkProps } from "./components/NavLink.js";
|
|
|
8
8
|
export { useRouter } from "./hooks/useRouter.js";
|
|
9
9
|
export { defineConfig } from "./runtime/defineConfig.js";
|
|
10
10
|
export { env, envAll } from "./runtime/env.js";
|
|
11
|
+
export { middlewareResponse } from "./runtime/middleware.js";
|
|
12
|
+
export type { MiddlewareConfig, MiddlewareFn, MiddlewareRequest, MiddlewareResponse } from "./runtime/middleware.js";
|
|
11
13
|
export type { LayoutProps } from "./runtime/types.js";
|
|
12
14
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,cAAc,EACd,WAAW,EACX,WAAW,EACX,SAAS,EACT,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,cAAc,EACd,WAAW,EACX,WAAW,EACX,SAAS,EACT,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACrH,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -5,3 +5,4 @@ export { NavLink } from "./components/NavLink.js";
|
|
|
5
5
|
export { useRouter } from "./hooks/useRouter.js";
|
|
6
6
|
export { defineConfig } from "./runtime/defineConfig.js";
|
|
7
7
|
export { env, envAll } from "./runtime/env.js";
|
|
8
|
+
export { middlewareResponse } from "./runtime/middleware.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { MiddlewareFn } from "../runtime/middleware.js";
|
|
3
|
+
type Props = {
|
|
4
|
+
middleware: MiddlewareFn;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
loadingFallback?: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
export declare function MiddlewareGuard({ middleware, children, loadingFallback }: Props): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=MiddlewareGuard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MiddlewareGuard.d.ts","sourceRoot":"","sources":["../../src/components/MiddlewareGuard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,KAAK,KAAK,GAAG;IACT,UAAU,EAAE,YAAY,CAAC;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACrC,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,KAAK,2CA4B/E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { useLocation, useNavigate } from "react-router-dom";
|
|
4
|
+
export function MiddlewareGuard({ middleware, children, loadingFallback }) {
|
|
5
|
+
const location = useLocation();
|
|
6
|
+
const navigate = useNavigate();
|
|
7
|
+
const [status, setStatus] = useState("pending");
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
setStatus("pending");
|
|
10
|
+
const request = {
|
|
11
|
+
pathname: location.pathname,
|
|
12
|
+
searchParams: new URLSearchParams(location.search),
|
|
13
|
+
};
|
|
14
|
+
Promise.resolve(middleware(request)).then((response) => {
|
|
15
|
+
if (response.type === "redirect") {
|
|
16
|
+
setStatus("redirecting");
|
|
17
|
+
navigate(response.destination, { replace: true });
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
setStatus("allowed");
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}, [location.pathname]);
|
|
24
|
+
if (status === "pending" || status === "redirecting") {
|
|
25
|
+
return _jsx(_Fragment, { children: loadingFallback ?? null });
|
|
26
|
+
}
|
|
27
|
+
return _jsx(_Fragment, { children: children });
|
|
28
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revinePlugin.d.ts","sourceRoot":"","sources":["../../../src/runtime/bundler/revinePlugin.ts"],"names":[],"mappings":"AA2VA,wBAAgB,YAAY,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"revinePlugin.d.ts","sourceRoot":"","sources":["../../../src/runtime/bundler/revinePlugin.ts"],"names":[],"mappings":"AA2VA,wBAAgB,YAAY,IAAI,GAAG,CA4LlC"}
|
|
@@ -365,12 +365,51 @@ export function revinePlugin() {
|
|
|
365
365
|
load(id) {
|
|
366
366
|
if (id === VIRTUAL_ROUTING_ID) {
|
|
367
367
|
return `
|
|
368
|
-
import { createBrowserRouter, useRouteError } from "react-router-dom";
|
|
369
|
-
import { lazy, Suspense, createElement } from "react";
|
|
368
|
+
import { createBrowserRouter, useRouteError, Outlet } from "react-router-dom";
|
|
369
|
+
import { lazy, Suspense, createElement, useState, useEffect, useRef } from "react";
|
|
370
370
|
import React from "react";
|
|
371
371
|
|
|
372
|
+
// ── Middleware support ──────────────────────────────────────────────
|
|
373
|
+
const middlewareModules = import.meta.glob("/src/middleware.{ts,tsx}", { eager: true });
|
|
374
|
+
const middlewareMod = Object.values(middlewareModules)[0];
|
|
375
|
+
const userMiddleware = middlewareMod?.default ?? null;
|
|
376
|
+
|
|
372
377
|
${errorBoundaryComponent}
|
|
373
378
|
|
|
379
|
+
// ── MiddlewareGuard ─────────────────────────────────────────────────
|
|
380
|
+
function MiddlewareGuard({ children }) {
|
|
381
|
+
const [status, setStatus] = React.useState("pending");
|
|
382
|
+
const lastPathnameRef = React.useRef(null);
|
|
383
|
+
|
|
384
|
+
React.useEffect(() => {
|
|
385
|
+
if (!userMiddleware) { setStatus("allowed"); return; }
|
|
386
|
+
|
|
387
|
+
const run = async (pathname, search) => {
|
|
388
|
+
if (pathname === lastPathnameRef.current) return;
|
|
389
|
+
lastPathnameRef.current = pathname;
|
|
390
|
+
|
|
391
|
+
setStatus("pending");
|
|
392
|
+
const req = { pathname, searchParams: new URLSearchParams(search) };
|
|
393
|
+
const res = await Promise.resolve(userMiddleware(req));
|
|
394
|
+
if (res.type === "redirect") {
|
|
395
|
+
router.navigate(res.destination, { replace: true });
|
|
396
|
+
setStatus("redirecting");
|
|
397
|
+
} else {
|
|
398
|
+
setStatus("allowed");
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
run(window.location.pathname, window.location.search);
|
|
403
|
+
|
|
404
|
+
return router.subscribe((state) => {
|
|
405
|
+
run(state.location.pathname, state.location.search);
|
|
406
|
+
});
|
|
407
|
+
}, []);
|
|
408
|
+
|
|
409
|
+
if (status === "pending" || status === "redirecting") return null;
|
|
410
|
+
return React.createElement(React.Fragment, null, children);
|
|
411
|
+
}
|
|
412
|
+
|
|
374
413
|
const notFoundModules = import.meta.glob("/src/NotFound.tsx", { eager: true });
|
|
375
414
|
const NotFoundComponent = Object.values(notFoundModules)[0]?.default;
|
|
376
415
|
|
|
@@ -430,7 +469,7 @@ const pageEntries = Object.entries(pages).filter(([filePath]) => {
|
|
|
430
469
|
return !segments.some((s) => s.startsWith("_"));
|
|
431
470
|
});
|
|
432
471
|
|
|
433
|
-
const
|
|
472
|
+
const innerRoutes = pageEntries.map(([filePath, component]) => {
|
|
434
473
|
const routePath = toRoutePath(filePath);
|
|
435
474
|
const Component = lazy(component);
|
|
436
475
|
const layouts = getLayoutsForPath(filePath);
|
|
@@ -453,7 +492,7 @@ const routes = pageEntries.map(([filePath, component]) => {
|
|
|
453
492
|
};
|
|
454
493
|
});
|
|
455
494
|
|
|
456
|
-
|
|
495
|
+
innerRoutes.push({
|
|
457
496
|
path: "*",
|
|
458
497
|
element: NotFoundComponent
|
|
459
498
|
? createElement(NotFoundComponent)
|
|
@@ -461,6 +500,14 @@ routes.push({
|
|
|
461
500
|
errorElement: createElement(RevineErrorDialog),
|
|
462
501
|
});
|
|
463
502
|
|
|
503
|
+
const routes = [
|
|
504
|
+
{
|
|
505
|
+
element: createElement(MiddlewareGuard, null, createElement(Outlet)),
|
|
506
|
+
children: innerRoutes,
|
|
507
|
+
errorElement: createElement(RevineErrorDialog),
|
|
508
|
+
},
|
|
509
|
+
];
|
|
510
|
+
|
|
464
511
|
export const router = createBrowserRouter(routes, {
|
|
465
512
|
future: {
|
|
466
513
|
v7_startTransition: true,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type MiddlewareRequest = {
|
|
2
|
+
pathname: string;
|
|
3
|
+
searchParams: URLSearchParams;
|
|
4
|
+
};
|
|
5
|
+
export type MiddlewareResponse = {
|
|
6
|
+
type: "next";
|
|
7
|
+
} | {
|
|
8
|
+
type: "redirect";
|
|
9
|
+
destination: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const middlewareResponse: {
|
|
12
|
+
next: () => MiddlewareResponse;
|
|
13
|
+
redirect: (destination: string) => MiddlewareResponse;
|
|
14
|
+
};
|
|
15
|
+
export type MiddlewareFn = (request: MiddlewareRequest) => MiddlewareResponse | Promise<MiddlewareResponse>;
|
|
16
|
+
export type MiddlewareConfig = {
|
|
17
|
+
publicPaths?: string[];
|
|
18
|
+
authPaths?: string[];
|
|
19
|
+
redirects?: {
|
|
20
|
+
whenAuthenticated?: string;
|
|
21
|
+
whenUnauthenticated?: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/runtime/middleware.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,eAAe,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C,eAAO,MAAM,kBAAkB;gBACnB,kBAAkB;4BACJ,MAAM,KAAG,kBAAkB;CAIpD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,OAAO,EAAE,iBAAiB,KACvB,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEtD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE;QACV,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH,CAAC"}
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -15,4 +15,6 @@ export type { NavLinkProps } from "./components/NavLink.js";
|
|
|
15
15
|
export { useRouter } from "./hooks/useRouter.js";
|
|
16
16
|
export { defineConfig } from "./runtime/defineConfig.js";
|
|
17
17
|
export { env, envAll } from "./runtime/env.js";
|
|
18
|
+
export { middlewareResponse } from "./runtime/middleware.js";
|
|
19
|
+
export type { MiddlewareConfig, MiddlewareFn, MiddlewareRequest, MiddlewareResponse } from "./runtime/middleware.js";
|
|
18
20
|
export type { LayoutProps } from "./runtime/types.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { useLocation, useNavigate } from "react-router-dom";
|
|
3
|
+
import type { MiddlewareFn } from "../runtime/middleware.js";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
middleware: MiddlewareFn;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
loadingFallback?: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function MiddlewareGuard({ middleware, children, loadingFallback }: Props) {
|
|
12
|
+
const location = useLocation();
|
|
13
|
+
const navigate = useNavigate();
|
|
14
|
+
const [status, setStatus] = useState<"pending" | "allowed" | "redirecting">("pending");
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
setStatus("pending");
|
|
18
|
+
|
|
19
|
+
const request = {
|
|
20
|
+
pathname: location.pathname,
|
|
21
|
+
searchParams: new URLSearchParams(location.search),
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
Promise.resolve(middleware(request)).then((response) => {
|
|
25
|
+
if (response.type === "redirect") {
|
|
26
|
+
setStatus("redirecting");
|
|
27
|
+
navigate(response.destination, { replace: true });
|
|
28
|
+
} else {
|
|
29
|
+
setStatus("allowed");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}, [location.pathname]);
|
|
33
|
+
|
|
34
|
+
if (status === "pending" || status === "redirecting") {
|
|
35
|
+
return <>{loadingFallback ?? null}</>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return <>{children}</>;
|
|
39
|
+
}
|
|
@@ -380,12 +380,51 @@ export function revinePlugin(): any {
|
|
|
380
380
|
load(id: string) {
|
|
381
381
|
if (id === VIRTUAL_ROUTING_ID) {
|
|
382
382
|
return `
|
|
383
|
-
import { createBrowserRouter, useRouteError } from "react-router-dom";
|
|
384
|
-
import { lazy, Suspense, createElement } from "react";
|
|
383
|
+
import { createBrowserRouter, useRouteError, Outlet } from "react-router-dom";
|
|
384
|
+
import { lazy, Suspense, createElement, useState, useEffect, useRef } from "react";
|
|
385
385
|
import React from "react";
|
|
386
386
|
|
|
387
|
+
// ── Middleware support ──────────────────────────────────────────────
|
|
388
|
+
const middlewareModules = import.meta.glob("/src/middleware.{ts,tsx}", { eager: true });
|
|
389
|
+
const middlewareMod = Object.values(middlewareModules)[0];
|
|
390
|
+
const userMiddleware = middlewareMod?.default ?? null;
|
|
391
|
+
|
|
387
392
|
${errorBoundaryComponent}
|
|
388
393
|
|
|
394
|
+
// ── MiddlewareGuard ─────────────────────────────────────────────────
|
|
395
|
+
function MiddlewareGuard({ children }) {
|
|
396
|
+
const [status, setStatus] = React.useState("pending");
|
|
397
|
+
const lastPathnameRef = React.useRef(null);
|
|
398
|
+
|
|
399
|
+
React.useEffect(() => {
|
|
400
|
+
if (!userMiddleware) { setStatus("allowed"); return; }
|
|
401
|
+
|
|
402
|
+
const run = async (pathname, search) => {
|
|
403
|
+
if (pathname === lastPathnameRef.current) return;
|
|
404
|
+
lastPathnameRef.current = pathname;
|
|
405
|
+
|
|
406
|
+
setStatus("pending");
|
|
407
|
+
const req = { pathname, searchParams: new URLSearchParams(search) };
|
|
408
|
+
const res = await Promise.resolve(userMiddleware(req));
|
|
409
|
+
if (res.type === "redirect") {
|
|
410
|
+
router.navigate(res.destination, { replace: true });
|
|
411
|
+
setStatus("redirecting");
|
|
412
|
+
} else {
|
|
413
|
+
setStatus("allowed");
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
run(window.location.pathname, window.location.search);
|
|
418
|
+
|
|
419
|
+
return router.subscribe((state) => {
|
|
420
|
+
run(state.location.pathname, state.location.search);
|
|
421
|
+
});
|
|
422
|
+
}, []);
|
|
423
|
+
|
|
424
|
+
if (status === "pending" || status === "redirecting") return null;
|
|
425
|
+
return React.createElement(React.Fragment, null, children);
|
|
426
|
+
}
|
|
427
|
+
|
|
389
428
|
const notFoundModules = import.meta.glob("/src/NotFound.tsx", { eager: true });
|
|
390
429
|
const NotFoundComponent = Object.values(notFoundModules)[0]?.default;
|
|
391
430
|
|
|
@@ -445,7 +484,7 @@ const pageEntries = Object.entries(pages).filter(([filePath]) => {
|
|
|
445
484
|
return !segments.some((s) => s.startsWith("_"));
|
|
446
485
|
});
|
|
447
486
|
|
|
448
|
-
const
|
|
487
|
+
const innerRoutes = pageEntries.map(([filePath, component]) => {
|
|
449
488
|
const routePath = toRoutePath(filePath);
|
|
450
489
|
const Component = lazy(component);
|
|
451
490
|
const layouts = getLayoutsForPath(filePath);
|
|
@@ -468,7 +507,7 @@ const routes = pageEntries.map(([filePath, component]) => {
|
|
|
468
507
|
};
|
|
469
508
|
});
|
|
470
509
|
|
|
471
|
-
|
|
510
|
+
innerRoutes.push({
|
|
472
511
|
path: "*",
|
|
473
512
|
element: NotFoundComponent
|
|
474
513
|
? createElement(NotFoundComponent)
|
|
@@ -476,6 +515,14 @@ routes.push({
|
|
|
476
515
|
errorElement: createElement(RevineErrorDialog),
|
|
477
516
|
});
|
|
478
517
|
|
|
518
|
+
const routes = [
|
|
519
|
+
{
|
|
520
|
+
element: createElement(MiddlewareGuard, null, createElement(Outlet)),
|
|
521
|
+
children: innerRoutes,
|
|
522
|
+
errorElement: createElement(RevineErrorDialog),
|
|
523
|
+
},
|
|
524
|
+
];
|
|
525
|
+
|
|
479
526
|
export const router = createBrowserRouter(routes, {
|
|
480
527
|
future: {
|
|
481
528
|
v7_startTransition: true,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type MiddlewareRequest = {
|
|
2
|
+
pathname: string;
|
|
3
|
+
searchParams: URLSearchParams;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type MiddlewareResponse =
|
|
7
|
+
| { type: "next" }
|
|
8
|
+
| { type: "redirect"; destination: string };
|
|
9
|
+
|
|
10
|
+
export const middlewareResponse = {
|
|
11
|
+
next: (): MiddlewareResponse => ({ type: "next" }),
|
|
12
|
+
redirect: (destination: string): MiddlewareResponse => ({
|
|
13
|
+
type: "redirect",
|
|
14
|
+
destination,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type MiddlewareFn = (
|
|
19
|
+
request: MiddlewareRequest,
|
|
20
|
+
) => MiddlewareResponse | Promise<MiddlewareResponse>;
|
|
21
|
+
|
|
22
|
+
export type MiddlewareConfig = {
|
|
23
|
+
publicPaths?: string[]; // paths accessible WITHOUT login
|
|
24
|
+
authPaths?: string[]; // paths only for GUESTS (login, register)
|
|
25
|
+
redirects?: {
|
|
26
|
+
whenAuthenticated?: string; // redirect auth pages to (default: "/")
|
|
27
|
+
whenUnauthenticated?: string; // redirect private pages to (default: "/login")
|
|
28
|
+
};
|
|
29
|
+
};
|