Skip to content

Commit

Permalink
feat: allow beta router to handle univeral links with need for prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
andyschwob committed Apr 9, 2021
1 parent ceb0c35 commit 70afa5b
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ const styles = StyleSheet.create({
}
});

const extractDevRoutes = (routes?: Routes, prefix: string= ''): string[] => {
const extractDevRoutes = (routes?: Routes): string[] => {
return (
routes?.reduce<string[]>(
(prev, route) => [
...prev,
...((('component' in route || 'loadComponent' in route) && route.quickDevMenu) ||
'children' in route
? [
`${prefix}/${route.path ?? ''}`,
'initialPath' in route ? `/${route.initialPath ?? ''}` : `/${route.path ?? ''}`,
...('children' in route
? extractDevRoutes(route.children, `${prefix}/${route.path ?? ''}`)
? extractDevRoutes(route.children)
: [])
]
: [])
Expand Down
5 changes: 2 additions & 3 deletions packages/fsapp/src/beta-app/router/history/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,10 @@ export class History implements FSRouterHistory {

constructor(private readonly routes: Routes) {
this.observeNavigation();

const tabRoutes = this.routes.filter(isTabRoute);
const universalRoutes = this.routes.filter(isNotTabRoute);
const stackMatchers = tabRoutes.map(({ children, tab, path }) =>
buildMatchers(children, tab, path ? `/${path}` : undefined)
const stackMatchers = tabRoutes.map(({ children, tab }) =>
buildMatchers(children, tab)
);

const promisedStacks = tabRoutes.map((route, i) => matchStack(route, stackMatchers[i]));
Expand Down
13 changes: 5 additions & 8 deletions packages/fsapp/src/beta-app/router/history/utils.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,14 @@ const matchPath = (path: string | undefined, route: Route) => {

const buildMatcher = async (
route: Route,
tab?: Tab,
prefix = ''
tab?: Tab
): Promise<
(readonly [
(checkPath: string) => { params: RouteParams } | undefined,
IndexedComponentRoute | RedirectRoute
])[]
> => {
const { id, path } = buildPath(route, prefix);

const { id, path } = buildPath(route);
const matchingRoute =
'component' in route || 'loadComponent' in route
? ([
Expand All @@ -94,7 +92,7 @@ const buildMatcher = async (
const children =
!matchingRoute && !matchingRedirect
? await mapPromisedChildren(route, childRoute =>
buildMatcher(childRoute, 'tab' in route ? route.tab ?? tab : tab, path)
buildMatcher(childRoute, tab)
)
: [];

Expand All @@ -107,12 +105,11 @@ const buildMatcher = async (

export const buildMatchers = async (
routes: Routes,
tab?: Tab,
prefix?: string
tab?: Tab
) => {
try {
return routes
.map(route => buildMatcher(route, tab, prefix))
.map(route => buildMatcher(route, 'tab' in route ? route.tab : tab))
.reduce(async (prev, next) => [...(await prev), ...(await next)], Promise.resolve([]));
} catch (e) {
return [];
Expand Down
17 changes: 11 additions & 6 deletions packages/fsapp/src/beta-app/router/history/utils.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
MatchingRoute,
ParentRoute,
Route,
TopLevelParentRoute
RouteCollection
} from '../types';

import React from 'react';
Expand All @@ -15,9 +15,9 @@ import { defaultsDeep, uniqueId } from 'lodash-es';
import { Matchers, matchRoute } from './utils.base';
import { ROOT_STACK } from './constants';

export const isTabRoute = (route: Route): route is TopLevelParentRoute => 'tab' in route;
export const isTabRoute = (route: Route): route is RouteCollection => 'tab' in route;

export const isNotTabRoute = (route: Route): route is Exclude<Route, TopLevelParentRoute> =>
export const isNotTabRoute = (route: Route): route is Exclude<Route, RouteCollection> =>
!('tab' in route);

export const createStack = ([route, title]: readonly [
Expand Down Expand Up @@ -65,8 +65,13 @@ export const createKey = () => {
return Math.random().toString(36).substr(2, 8);
};

export const applyMatcher = async (matchers: Matchers, { path }: ParentRoute) => {
const component = await matchRoute(matchers, path ? `/${path}` : '/');
export const applyMatcher = async (matchers: Matchers, route: RouteCollection | ParentRoute) => {
const component =
await matchRoute(
matchers,
'initialPath' in route
? `/${route.initialPath}`
: route.path ? `/${route.path}` : '/');
if (component) {
const title =
typeof component.title === 'function'
Expand All @@ -84,7 +89,7 @@ export const applyMatcher = async (matchers: Matchers, { path }: ParentRoute) =>
return undefined;
};

export const matchStack = async (route: ParentRoute, matcher: Matchers) => {
export const matchStack = async (route: RouteCollection | ParentRoute, matcher: Matchers) => {
const component = await applyMatcher(matcher, route);
return component ? createStack(component) : undefined;
};
Expand Down
2 changes: 1 addition & 1 deletion packages/fsapp/src/beta-app/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type {
MatchingRoute,
Routes,
Tab,
TopLevelParentRoute,
RouteCollection,
TopBarStyle,
ExternalRoute,
ExternalRoutes,
Expand Down
7 changes: 3 additions & 4 deletions packages/fsapp/src/beta-app/router/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
FSRouterConstructor,
InternalRouterConfig,
Route,
RouteCollection,
RouterConfig,
Routes
} from './types';
Expand Down Expand Up @@ -51,7 +52,6 @@ export class FSRouter extends FSRouterBase {

private registerRoutes(
routes: Routes | ExternalRoutes,
prefix: string = '',
tab?: string | OptionsBottomTab
): void {
let routeDetails = defaultActivatedRoute;
Expand All @@ -60,8 +60,8 @@ export class FSRouter extends FSRouterBase {
});
const addedRoutes = new Set<string>();

routes.forEach((route: Route | ExternalRoute) => {
const { path, id } = buildPath(route, prefix);
routes.forEach((route: RouteCollection | Route | ExternalRoute) => {
const { path, id } = buildPath(route);
if (!addedRoutes.has(id)) {
const LoadingPlaceholder = () => <>{this.options.loading}</>;
if ('component' in route || 'loadComponent' in route) {
Expand Down Expand Up @@ -113,7 +113,6 @@ export class FSRouter extends FSRouterBase {
const tabAffinity = 'tab' in route ? route.tab : tab;
this.registerRoutes(
route.children,
path,
'tabAffinity' in route ? route.tabAffinity : tabAffinity
);
}
Expand Down
7 changes: 3 additions & 4 deletions packages/fsapp/src/beta-app/router/router.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ export class FSRouter extends FSRouterBase {
private constructScreen = (
route: Route,
loading: boolean,
routeDetails: ActivatedRoute,
prefix?: string
routeDetails: ActivatedRoute
): JSX.Element | JSX.Element[] => {
const { id, path } = useMemo(() => buildPath(route, prefix), []);
const { id, path } = useMemo(() => buildPath(route), []);

if ('loadComponent' in route || 'component' in route) {
const [filteredRoute, setFilteredRoute] = useState(() => routeDetails);
Expand Down Expand Up @@ -101,7 +100,7 @@ export class FSRouter extends FSRouterBase {
return <Redirect key={id} path={path} to={route.redirect} exact={route.exact} />;
} else if ('children' in route) {
return route.children
.map(child => this.constructScreen(child, loading, routeDetails, path))
.map(child => this.constructScreen(child, loading, routeDetails))
.reduce<JSX.Element[]>(
(prev, next) => [...prev, ...(Array.isArray(next) ? next : [next])],
[]
Expand Down
11 changes: 6 additions & 5 deletions packages/fsapp/src/beta-app/router/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,11 @@ export interface ParentRoute extends BaseRoute {
readonly children: (Route & { tab?: never })[];
}

export interface TopLevelParentRoute extends ParentRoute {
readonly path: Exclude<string, ''>;
// initial path required
export interface RouteCollection {
readonly initialPath: Exclude<string, ''>;
readonly tab: Tab;
readonly children: (Route & { tab?: never })[];
}

export interface RedirectRoute extends BaseRoute {
Expand Down Expand Up @@ -156,14 +158,13 @@ export type Route =
| ComponentRoute
| LazyComponentRoute
| RedirectRoute
| ParentRoute
| TopLevelParentRoute;
| ParentRoute;

/**
* A list of routes
* @see Route
*/
export type Routes = readonly Route[];
export type Routes = readonly (Route | RouteCollection)[];

export type ExternalRoute = Route & { readonly tabAffinity?: string };
export type ExternalRoutes = readonly ExternalRoute[];
Expand Down
8 changes: 4 additions & 4 deletions packages/fsapp/src/beta-app/router/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const resolveRoutes = async ({
(await (typeof externalRoutesFactory === 'function'
? externalRoutesFactory(api)
: externalRoutesFactory)) ?? [];

// tslint:disable-next-line: cyclomatic-complexity
const findRoute = (
search: ExternalRoute,
children = routes,
Expand All @@ -28,7 +28,8 @@ export const resolveRoutes = async ({
for (const child of children) {
// Replace Variables
const searchPath = search.path?.replace(/:\w+(?=\/)?/, ':') ?? '';
const childPath = child.path?.replace(/:\w+(?=\/)?/, ':') ?? '';
const childPath = ('initialPath' in child ? child.initialPath : child.path)
?.replace(/:\w+(?=\/)?/, ':') ?? '';
const prefixedPath = `${prefix}/${childPath}`;

const tab = 'tab' in child ? child.tab : tabAffinity;
Expand Down Expand Up @@ -72,8 +73,7 @@ export const resolveRoutes = async ({
)
.map(external => ({
...external,
path: external.path?.replace(`${route.path}`, '')
.replace(/\/$/, '').replace(/^\//, '')
path: external.path?.replace(/\/$/, '').replace(/^\//, '')
})),
...route.children
]
Expand Down
15 changes: 8 additions & 7 deletions packages/fsapp/src/beta-app/utils.base.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Dictionary } from '@brandingbrand/fsfoundation';
import type { Route } from './router';
import type { Route, RouteCollection } from './router';

import loadable from '@loadable/component';
import { fromPairs } from 'lodash-es';
Expand All @@ -10,12 +10,13 @@ export const StaticImplements = <T extends any>() => <U extends T>(_constructor:

export const isDefined = <T extends any>(value: T | undefined): value is T => value !== undefined;

export const buildPath = (route: Route, prefix?: string) => {
const path =
route.path !== undefined
? `${prefix?.replace(/\/$/, '') ?? ''}/${route.path?.replace(/^\//, '') ?? ''}`
: prefix;
const id = path || `${prefix ?? ''}/undefined`;
export const buildPath = (route: Route | RouteCollection) => {
const path = 'initialPath' in route
? `/${route.initialPath?.replace(/^\//, '') ?? ''}`
: route.path !== undefined
? `/${route.path?.replace(/^\//, '') ?? ''}`
: '/';
const id = path || `/undefined`;
return { id, path };
};

Expand Down

0 comments on commit 70afa5b

Please sign in to comment.