Skip to content

Commit

Permalink
feat(plugin-history-sync): sort routes by variable count (#448)
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyfromundefined authored Feb 5, 2024
1 parent ffa4c06 commit 36613e3
Show file tree
Hide file tree
Showing 18 changed files with 178 additions and 98 deletions.
7 changes: 7 additions & 0 deletions .changeset/spotty-parrots-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@stackflow/plugin-history-sync": minor
"@stackflow/plugin-preload": minor
"@stackflow/link": minor
---

Sort routes by variable count and refactor useRoutes(), normalizeRouteInput() function
15 changes: 4 additions & 11 deletions extensions/link/src/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import type { UrlPatternOptions } from "@stackflow/plugin-history-sync";
import {
makeTemplate,
normalizeRoute,
useRoutes,
} from "@stackflow/plugin-history-sync";
import { makeTemplate, useRoutes } from "@stackflow/plugin-history-sync";
import { usePreloader } from "@stackflow/plugin-preload";
import type { ActivityComponentType } from "@stackflow/react";
import { useActions } from "@stackflow/react";
Expand Down Expand Up @@ -44,16 +40,13 @@ export const Link: TypeLink = forwardRef(
const [preloaded, flagPreloaded] = useReducer(() => true, false);

const href = useMemo(() => {
const route = routes[props.activityName];
const match = routes.find((r) => r.activityName === props.activityName);

if (!route) {
if (!match) {
return undefined;
}

const template = makeTemplate(
normalizeRoute(route)[0],
props.urlPatternOptions,
);
const template = makeTemplate(match.path, props.urlPatternOptions);
const path = template.fill(props.activityParams);

return path;
Expand Down
4 changes: 4 additions & 0 deletions extensions/plugin-history-sync/src/ActivityRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type ActivityRoute = {
activityName: string;
path: string;
};
3 changes: 3 additions & 0 deletions extensions/plugin-history-sync/src/ActivityRouteMapInput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type ActivityRouteMapInput = {
[activityName in string]?: string | string[];
};
8 changes: 3 additions & 5 deletions extensions/plugin-history-sync/src/RoutesContext.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { createContext, useContext } from "react";

export type RoutesMap = {
[activityName in string]?: string | string[];
};
import type { ActivityRoute } from "./ActivityRoute";

export const RoutesContext = createContext<RoutesMap>({});
export const RoutesContext = createContext<ActivityRoute[]>([]);

interface RoutesProviderProps {
routes: RoutesMap;
routes: ActivityRoute[];
children: React.ReactNode;
}
export const RoutesProvider: React.FC<RoutesProviderProps> = (props) => (
Expand Down
112 changes: 56 additions & 56 deletions extensions/plugin-history-sync/src/historySyncPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import {
safeParseState,
} from "./historyState";
import { last } from "./last";
import { makeHistoryTaskQueue } from "./makeHistoryTaskQueue";
import type { UrlPatternOptions } from "./makeTemplate";
import { makeTemplate } from "./makeTemplate";
import { normalizeRoute } from "./normalizeRoute";
import { makeHistoryTaskQueue } from "./queue";
import { normalizeActivityRouteMap } from "./normalizeActivityRouteMap";
import { RoutesProvider } from "./RoutesContext";
import { sortActivityRoutes } from "./sortActivityRoutes";

const SECOND = 1000;
const MINUTE = 60 * SECOND;
Expand Down Expand Up @@ -46,6 +47,10 @@ export function historySyncPlugin<

const { location } = history;

const activityRoutes = sortActivityRoutes(
normalizeActivityRouteMap(options.routes),
);

return () => {
let pushFlag = 0;
let silentFlag = false;
Expand All @@ -57,7 +62,7 @@ export function historySyncPlugin<
wrapStack({ stack }) {
return (
<HistoryQueueProvider requestHistoryTick={requestHistoryTick}>
<RoutesProvider routes={options.routes}>
<RoutesProvider routes={activityRoutes}>
{stack.render()}
</RoutesProvider>
</HistoryQueueProvider>
Expand Down Expand Up @@ -86,7 +91,7 @@ export function historySyncPlugin<
];
}

function resolvePath() {
function resolveCurrentPath() {
if (
initialContext?.req?.path &&
typeof initialContext.req.path === "string"
Expand All @@ -101,34 +106,29 @@ export function historySyncPlugin<
return location.pathname + location.search;
}

const path = resolvePath();
const activityNames = Object.keys(options.routes);

if (path) {
for (const activityName of activityNames) {
const routes = normalizeRoute(options.routes[activityName as K]);

for (const route of routes) {
const template = makeTemplate(route, options.urlPatternOptions);
const activityParams = template.parse(path);

if (activityParams) {
const activityId = id();

return [
makeEvent("Pushed", {
activityId,
activityName,
activityParams: {
...activityParams,
},
eventDate: new Date().getTime() - MINUTE,
activityContext: {
path,
},
}),
];
}
const currentPath = resolveCurrentPath();

if (currentPath) {
for (const { activityName, path } of activityRoutes) {
const template = makeTemplate(path, options.urlPatternOptions);
const activityParams = template.parse(currentPath);

if (activityParams) {
const activityId = id();

return [
makeEvent("Pushed", {
activityId,
activityName,
activityParams: {
...activityParams,
},
eventDate: new Date().getTime() - MINUTE,
activityContext: {
path: currentPath,
},
}),
];
}
}
}
Expand All @@ -137,10 +137,10 @@ export function historySyncPlugin<
const fallbackActivityName = options.fallbackActivity({
initialContext,
});
const fallbackActivityRoutes = normalizeRoute(
options.routes[fallbackActivityName],
const fallbackActivityRoute = activityRoutes.find(
(r) => r.activityName === fallbackActivityName,
);
const fallbackActivityPath = fallbackActivityRoutes[0];
const fallbackActivityPath = fallbackActivityRoute?.path;

return [
makeEvent("Pushed", {
Expand All @@ -157,10 +157,10 @@ export function historySyncPlugin<
onInit({ actions: { getStack, dispatchEvent, push, stepPush } }) {
const rootActivity = getStack().activities[0];

const template = makeTemplate(
normalizeRoute(options.routes[rootActivity.name])[0],
options.urlPatternOptions,
const match = activityRoutes.find(
(r) => r.activityName === rootActivity.name,
);
const template = makeTemplate(match!.path, options.urlPatternOptions);

const lastStep = last(rootActivity.steps);

Expand Down Expand Up @@ -311,10 +311,10 @@ export function historySyncPlugin<
return;
}

const template = makeTemplate(
normalizeRoute(options.routes[activity.name])[0],
options.urlPatternOptions,
const match = activityRoutes.find(
(r) => r.activityName === activity.name,
);
const template = makeTemplate(match!.path, options.urlPatternOptions);

requestHistoryTick(() => {
silentFlag = true;
Expand All @@ -334,10 +334,10 @@ export function historySyncPlugin<
return;
}

const template = makeTemplate(
normalizeRoute(options.routes[activity.name])[0],
options.urlPatternOptions,
const match = activityRoutes.find(
(r) => r.activityName === activity.name,
);
const template = makeTemplate(match!.path, options.urlPatternOptions);

requestHistoryTick(() => {
silentFlag = true;
Expand All @@ -357,10 +357,10 @@ export function historySyncPlugin<
return;
}

const template = makeTemplate(
normalizeRoute(options.routes[activity.name])[0],
options.urlPatternOptions,
const match = activityRoutes.find(
(r) => r.activityName === activity.name,
);
const template = makeTemplate(match!.path, options.urlPatternOptions);

requestHistoryTick(() => {
silentFlag = true;
Expand All @@ -379,10 +379,10 @@ export function historySyncPlugin<
return;
}

const template = makeTemplate(
normalizeRoute(options.routes[activity.name])[0],
options.urlPatternOptions,
const match = activityRoutes.find(
(r) => r.activityName === activity.name,
);
const template = makeTemplate(match!.path, options.urlPatternOptions);

requestHistoryTick(() => {
silentFlag = true;
Expand All @@ -398,10 +398,10 @@ export function historySyncPlugin<
});
},
onBeforePush({ actionParams, actions: { overrideActionParams } }) {
const template = makeTemplate(
normalizeRoute(options.routes[actionParams.activityName])[0],
options.urlPatternOptions,
const match = activityRoutes.find(
(r) => r.activityName === actionParams.activityName,
);
const template = makeTemplate(match!.path, options.urlPatternOptions);
const path = template.fill(actionParams.activityParams);

overrideActionParams({
Expand All @@ -416,10 +416,10 @@ export function historySyncPlugin<
actionParams,
actions: { overrideActionParams, getStack },
}) {
const template = makeTemplate(
normalizeRoute(options.routes[actionParams.activityName])[0],
options.urlPatternOptions,
const match = activityRoutes.find(
(r) => r.activityName === actionParams.activityName,
);
const template = makeTemplate(match!.path, options.urlPatternOptions);
const path = template.fill(actionParams.activityParams);

overrideActionParams({
Expand Down
1 change: 0 additions & 1 deletion extensions/plugin-history-sync/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export { useHistoryTick } from "./HistoryQueueContext";
export * from "./historySyncPlugin";
export { makeTemplate, UrlPatternOptions } from "./makeTemplate";
export { normalizeRoute } from "./normalizeRoute";
export { useRoutes } from "./RoutesContext";
File renamed without changes.
5 changes: 3 additions & 2 deletions extensions/plugin-history-sync/src/makeTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ export interface UrlPatternOptions {
}

export function makeTemplate(
templateStr: string,
path: string,
urlPatternOptions?: UrlPatternOptions,
) {
const pattern = new UrlPattern(`${templateStr}(/)`, urlPatternOptions);
const pattern = new UrlPattern(`${path}(/)`, urlPatternOptions);

return {
fill(params: { [key: string]: string | undefined }) {
Expand Down Expand Up @@ -95,5 +95,6 @@ export function makeTemplate(
...pathParams,
};
},
variableCount: (pattern as any).names.length,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { normalizeActivityRouteMap } from "./normalizeActivityRouteMap";

test("normalizeActivityRouteMap", () => {
expect(
normalizeActivityRouteMap({
Hello: ["/hello", "/hello-2"],
World: "/world",
}),
).toStrictEqual([
{
activityName: "Hello",
path: "/hello",
},
{
activityName: "Hello",
path: "/hello-2",
},
{
activityName: "World",
path: "/world",
},
]);
});
22 changes: 22 additions & 0 deletions extensions/plugin-history-sync/src/normalizeActivityRouteMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { ActivityRoute } from "./ActivityRoute";
import type { ActivityRouteMapInput } from "./ActivityRouteMapInput";
import { normalizeRouteInput } from "./normalizeRouteInput";

export function normalizeActivityRouteMap<T extends ActivityRouteMapInput>(
activityRouteMap: T,
): ActivityRoute[] {
const routes = Object.keys(activityRouteMap).flatMap((activityName) => {
const routeInput = activityRouteMap[activityName];

if (!routeInput) {
return [];
}

return normalizeRouteInput(routeInput).map((path) => ({
activityName,
path,
}));
});

return routes;
}
9 changes: 0 additions & 9 deletions extensions/plugin-history-sync/src/normalizeRoute.spec.ts

This file was deleted.

3 changes: 0 additions & 3 deletions extensions/plugin-history-sync/src/normalizeRoute.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { normalizeRouteInput } from "./normalizeRouteInput";

test("normalizeRouteInput - string이 들어오면 [string]으로 만듭니다", () => {
expect(normalizeRouteInput("/home")).toEqual(["/home"]);
});

test("normalizeRouteInput - string[]이 들어오면 string[]인채로 반환합니다", () => {
expect(normalizeRouteInput(["/home"])).toEqual(["/home"]);
});
3 changes: 3 additions & 0 deletions extensions/plugin-history-sync/src/normalizeRouteInput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function normalizeRouteInput(route: string | string[]) {
return typeof route === "string" ? [route] : route;
}
Loading

0 comments on commit 36613e3

Please sign in to comment.