@furystack/shades
Version:
Google Authentication Provider for FuryStack
61 lines • 2.8 kB
JavaScript
import { ObservableAlreadyDisposedError } from '@furystack/utils';
import { match } from 'path-to-regexp';
import { Lock } from 'semaphore-async-await';
import { LocationService } from '../services/location-service.js';
import { createComponent } from '../shade-component.js';
import { Shade } from '../shade.js';
export const Router = Shade({
shadowDomName: 'shade-router',
render: (options) => {
const { useState, useObservable, injector } = options;
const [lock] = useState('lock', new Lock());
const [state, setState] = useState('routerState', {
jsx: createComponent("div", null),
});
const updateUrl = async (currentUrl) => {
const [lastState] = useState('routerState', state);
const { activeRoute: lastRoute, activeRouteParams: lastRouteParams, jsx: lastJsx } = lastState;
try {
await lock.acquire();
for (const route of options.props.routes) {
const matchFn = match(route.url, route.routingOptions);
const matchResult = matchFn(currentUrl);
if (matchResult) {
if (route !== lastRoute || JSON.stringify(lastRouteParams) !== JSON.stringify(matchResult.params)) {
await lastRoute?.onLeave?.({ ...options, element: lastState.jsx });
const newJsx = route.component({ currentUrl, match: matchResult });
setState({ jsx: newJsx, activeRoute: route, activeRouteParams: matchResult.params });
await route.onVisit?.({ ...options, element: newJsx });
}
return;
}
}
if (lastRoute !== null) {
await lastRoute?.onLeave?.({ ...options, element: lastJsx });
setState({
jsx: options.props.notFound || createComponent("div", null),
activeRoute: null,
activeRouteParams: null,
});
}
}
catch (e) {
// path updates can be async, this can be ignored
if (!(e instanceof ObservableAlreadyDisposedError)) {
throw e;
}
}
finally {
lock?.release();
}
};
const [locationPath] = useObservable('locationPathChanged', injector.getInstance(LocationService).onLocationPathChanged, {
onChange: (newValue) => {
void updateUrl(newValue);
},
});
void updateUrl(locationPath);
return state.jsx;
},
});
//# sourceMappingURL=router.js.map