feat(navigation): add external entry routing
This commit is contained in:
@@ -10,15 +10,12 @@ describe("route meta", () => {
|
||||
expect(getRouteAccess(ROUTES.chat)).toBe("guestEntry");
|
||||
expect(getRouteAccess(ROUTES.privateRoom)).toBe("guestEntry");
|
||||
expect(getRouteAccess(ROUTES.tip)).toBe("public");
|
||||
expect(getRouteAccess(ROUTES.externalEntry)).toBe("public");
|
||||
expect(getRouteAccess(ROUTES.sidebar)).toBe("session");
|
||||
expect(getRouteAccess(ROUTES.subscription)).toBe("realUser");
|
||||
expect(getRouteAccess(ROUTES.coinsRules)).toBe("public");
|
||||
});
|
||||
|
||||
it("classifies known dynamic chat routes", () => {
|
||||
expect(getRouteAccess("/chat/deviceid/device_1")).toBe("public");
|
||||
});
|
||||
|
||||
it("does not keep the removed chat image route as a guarded route", () => {
|
||||
expect(getRouteAccess("/chat/image/msg_1")).toBe("public");
|
||||
});
|
||||
@@ -31,6 +28,10 @@ describe("route meta", () => {
|
||||
expect(ALL_STATIC_ROUTES).toContain(ROUTES.tip);
|
||||
});
|
||||
|
||||
it("includes external entry in static routes", () => {
|
||||
expect(ALL_STATIC_ROUTES).toContain(ROUTES.externalEntry);
|
||||
});
|
||||
|
||||
it("treats unknown routes as public by default", () => {
|
||||
expect(getRouteAccess("/unknown")).toBe("public");
|
||||
});
|
||||
|
||||
@@ -14,13 +14,13 @@ const STATIC_ROUTE_ACCESS: Partial<Record<string, RouteAccess>> = {
|
||||
[ROUTES.chat]: "guestEntry",
|
||||
[ROUTES.privateRoom]: "guestEntry",
|
||||
[ROUTES.tip]: "public",
|
||||
[ROUTES.externalEntry]: "public",
|
||||
[ROUTES.sidebar]: "session",
|
||||
[ROUTES.subscription]: "realUser",
|
||||
[ROUTES.coinsRules]: "public",
|
||||
};
|
||||
|
||||
export function getRouteAccess(pathname: string): RouteAccess {
|
||||
if (pathname.startsWith("/chat/deviceid/")) return "public";
|
||||
return STATIC_ROUTE_ACCESS[pathname] ?? "public";
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 关键设计:
|
||||
* - `as const` 让每个值都是字符串字面量类型,可用于 `PageProps<'/literal'>`。
|
||||
* - 不导出 Client-only 模块(`use-auth-gate` 走独立路径导入),保证 Server bundle 不被污染。
|
||||
* - 动态深链通过 `ROUTE_BUILDERS` 函数生成,避免手拼字符串。
|
||||
* - 动态查询路由通过 `ROUTE_BUILDERS` 函数生成,避免手拼字符串。
|
||||
*/
|
||||
|
||||
import type { PayChannel } from "@/data/dto/payment";
|
||||
@@ -16,6 +16,7 @@ export const ROUTES = {
|
||||
chat: "/chat",
|
||||
privateRoom: "/private-room",
|
||||
tip: "/tip",
|
||||
externalEntry: "/external-entry",
|
||||
auth: "/auth",
|
||||
sidebar: "/sidebar",
|
||||
subscription: "/subscription",
|
||||
@@ -24,10 +25,8 @@ export const ROUTES = {
|
||||
|
||||
export type StaticRoute = (typeof ROUTES)[keyof typeof ROUTES];
|
||||
|
||||
/** 动态深链构造器 */
|
||||
/** 动态查询路由构造器 */
|
||||
export const ROUTE_BUILDERS = {
|
||||
chatDeviceId: (deviceId: string): `/chat/deviceid/${string}` =>
|
||||
`/chat/deviceid/${encodeURIComponent(deviceId)}` as const,
|
||||
subscription: (
|
||||
type: "vip" | "topup",
|
||||
options: { payChannel?: PayChannel; returnTo?: "chat" } = {},
|
||||
@@ -47,12 +46,11 @@ export const ALL_STATIC_ROUTES: readonly StaticRoute[] = [
|
||||
ROUTES.chat,
|
||||
ROUTES.privateRoom,
|
||||
ROUTES.tip,
|
||||
ROUTES.externalEntry,
|
||||
ROUTES.auth,
|
||||
ROUTES.sidebar,
|
||||
ROUTES.coinsRules,
|
||||
] as const;
|
||||
|
||||
/** 联合路由类型,包含静态路由与已知动态路由 */
|
||||
export type Route =
|
||||
| StaticRoute
|
||||
| `/chat/deviceid/${string}`;
|
||||
/** 联合路由类型 */
|
||||
export type Route = StaticRoute;
|
||||
|
||||
Reference in New Issue
Block a user