diff --git a/.changeset/two-hats-push.md b/.changeset/two-hats-push.md new file mode 100644 index 000000000..cf322a4a5 --- /dev/null +++ b/.changeset/two-hats-push.md @@ -0,0 +1,5 @@ +--- +"@stackflow/plugin-history-sync": minor +--- + +Allow setting priority for each route diff --git a/extensions/plugin-history-sync/src/RouteLike.ts b/extensions/plugin-history-sync/src/RouteLike.ts index aa6083fed..6400c288d 100644 --- a/extensions/plugin-history-sync/src/RouteLike.ts +++ b/extensions/plugin-history-sync/src/RouteLike.ts @@ -2,6 +2,7 @@ import type { ActivityComponentType } from "@stackflow/react"; export type Route = { path: string; + priority?: number; decode?: ( params: Record, ) => K extends ActivityComponentType ? U : {}; diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index e9a821a5d..3e62ed245 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -25,6 +25,7 @@ type ConfigHistorySync = { declare module "@stackflow/config" { interface ActivityDefinition { path: string; + routePriority?: number; } interface Config> { @@ -74,7 +75,10 @@ export function historySyncPlugin< : options.config.activities.reduce( (acc, a) => ({ ...acc, - [a.name]: a.path, + [a.name]: { + path: a.path, + priority: a.routePriority + } }), {}, ); diff --git a/extensions/plugin-history-sync/src/sortActivityRoutes.spec.ts b/extensions/plugin-history-sync/src/sortActivityRoutes.spec.ts index a422ebb0f..845bac246 100644 --- a/extensions/plugin-history-sync/src/sortActivityRoutes.spec.ts +++ b/extensions/plugin-history-sync/src/sortActivityRoutes.spec.ts @@ -41,3 +41,35 @@ test("sortActivityRoutes - *이 들어간 경우 해당 라우트를 맨 뒤로 { activityName: "A", path: "*" }, ]); }); + +test("sortActivityRoutes - priority가 있는 경우 priority가 동일한 라우트들 간에 정렬됩니다", () => { + const routes = sortActivityRoutes([ + { activityName: "A", path: "*" }, + { activityName: "A", path: "/detailed/*" }, + { activityName: "B", path: "/:hello/:world" }, + { activityName: "C", path: "/:hello/:world/:foo/:bar" }, + { activityName: "A", priority: 1, path: "*" }, + { activityName: "A", priority: 1, path: "/detailed/*" }, + { activityName: "B", priority: 1, path: "/:hello/:world" }, + { activityName: "C", priority: 1, path: "/:hello/:world/:foo/:bar" }, + { activityName: "A", priority: -1, path: "*" }, + { activityName: "A", priority: -1, path: "/detailed/*" }, + { activityName: "B", priority: -1, path: "/:hello/:world" }, + { activityName: "C", priority: -1, path: "/:hello/:world/:foo/:bar" }, + ]); + + expect(routes).toStrictEqual([ + { activityName: "C", priority: 1, path: "/:hello/:world/:foo/:bar" }, + { activityName: "A", priority: 1, path: "/detailed/*" }, + { activityName: "B", priority: 1, path: "/:hello/:world" }, + { activityName: "A", priority: 1, path: "*" }, + { activityName: "C", path: "/:hello/:world/:foo/:bar" }, + { activityName: "A", path: "/detailed/*" }, + { activityName: "B", path: "/:hello/:world" }, + { activityName: "A", path: "*" }, + { activityName: "C", priority: -1, path: "/:hello/:world/:foo/:bar" }, + { activityName: "A", priority: -1, path: "/detailed/*" }, + { activityName: "B", priority: -1, path: "/:hello/:world" }, + { activityName: "A", priority: -1, path: "*" }, + ]); +}); diff --git a/extensions/plugin-history-sync/src/sortActivityRoutes.ts b/extensions/plugin-history-sync/src/sortActivityRoutes.ts index 8831120d8..e81c84475 100644 --- a/extensions/plugin-history-sync/src/sortActivityRoutes.ts +++ b/extensions/plugin-history-sync/src/sortActivityRoutes.ts @@ -34,7 +34,15 @@ function computeScore(path: string): number { export function sortActivityRoutes( routes: ActivityRoute[], ): ActivityRoute[] { - return [...routes].sort( - (a, b) => computeScore(b.path) - computeScore(a.path), - ); + const routesByPriority = routes.reduce((acc, route) => { + const array = acc.get(route.priority ?? 0); + if (array) array.push(route) + else acc.set(route.priority ?? 0, [route]); + return acc; + }, new Map[]>()); + return [...routesByPriority.entries()].sort( + ([priorityA], [priorityB]) => priorityB - priorityA, + ).flatMap(([_, routes]) => + routes.sort((a, b) => computeScore(b.path) - computeScore(a.path)), + ) }