You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-11-23 11:02:35 +03:00
137 lines
4.1 KiB
TypeScript
137 lines
4.1 KiB
TypeScript
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
export type Location = Readonly<{
|
|
pathname?: string;
|
|
searchParams?: URLSearchParams;
|
|
}>;
|
|
|
|
export type Segments = Readonly<string[]>;
|
|
|
|
// Converts a list of segments to a path
|
|
const segmentsToPath = (segments: Segments): string =>
|
|
segments.map((part) => encodeURIComponent(part)).join("/");
|
|
|
|
// Converts a path to a list of segments
|
|
const pathToSegments = (path: string): Segments =>
|
|
path.split("/").map(decodeURIComponent);
|
|
|
|
type ProfileRoute = Readonly<{ type: "profile" }>;
|
|
type SessionOverviewRoute = Readonly<{ type: "sessions-overview" }>;
|
|
type SessionDetailRoute = Readonly<{ type: "session"; id: string }>;
|
|
type OAuth2ClientRoute = Readonly<{ type: "client"; id: string }>;
|
|
type BrowserSessionRoute = Readonly<{ type: "browser-session"; id: string }>;
|
|
type BrowserSessionListRoute = Readonly<{ type: "browser-session-list" }>;
|
|
type VerifyEmailRoute = Readonly<{ type: "verify-email"; id: string }>;
|
|
type UnknownRoute = Readonly<{ type: "unknown"; segments: Segments }>;
|
|
|
|
export type Route =
|
|
| SessionOverviewRoute
|
|
| SessionDetailRoute
|
|
| ProfileRoute
|
|
| OAuth2ClientRoute
|
|
| BrowserSessionRoute
|
|
| BrowserSessionListRoute
|
|
| VerifyEmailRoute
|
|
| UnknownRoute;
|
|
|
|
// Converts a route to a path
|
|
export const routeToPath = (route: Route): string =>
|
|
segmentsToPath(routeToSegments(route));
|
|
|
|
// Converts a path to a route
|
|
export const pathToRoute = (path: string): Route =>
|
|
segmentsToRoute(pathToSegments(path));
|
|
|
|
// Converts a route to a list of segments
|
|
export const routeToSegments = (route: Route): Segments => {
|
|
switch (route.type) {
|
|
case "profile":
|
|
return [];
|
|
case "sessions-overview":
|
|
return ["sessions-overview"];
|
|
case "session":
|
|
return ["session", route.id];
|
|
case "verify-email":
|
|
return ["emails", route.id, "verify"];
|
|
case "client":
|
|
return ["clients", route.id];
|
|
case "browser-session-list":
|
|
return ["browser-sessions"];
|
|
case "browser-session":
|
|
return ["browser-sessions", route.id];
|
|
case "unknown":
|
|
return route.segments;
|
|
}
|
|
};
|
|
|
|
const P = Symbol();
|
|
type PatternItem = string | typeof P;
|
|
|
|
// Returns true if the segments match the pattern, where P is a parameter
|
|
const segmentMatches = (
|
|
segments: Segments,
|
|
...pattern: PatternItem[]
|
|
): boolean => {
|
|
// Quick check to see if the lengths match
|
|
if (segments.length !== pattern.length) return false;
|
|
|
|
// Check each segment
|
|
for (let i = 0; i < segments.length; i++) {
|
|
// If the pattern is P, then it's a parameter and we can skip it
|
|
if (pattern[i] === P) continue;
|
|
// Otherwise, check that the segment matches the pattern
|
|
if (segments[i] !== pattern[i]) return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
// Converts a list of segments to a route
|
|
export const segmentsToRoute = (segments: Segments): Route => {
|
|
const matches = (...pattern: PatternItem[]): boolean =>
|
|
segmentMatches(segments, ...pattern);
|
|
|
|
// Special case for the home page
|
|
if (matches() || matches("")) {
|
|
return { type: "profile" };
|
|
}
|
|
|
|
if (matches("sessions-overview")) {
|
|
return { type: "sessions-overview" };
|
|
}
|
|
|
|
if (matches("browser-sessions")) {
|
|
return { type: "browser-session-list" };
|
|
}
|
|
|
|
if (matches("emails", P, "verify")) {
|
|
return { type: "verify-email", id: segments[1] };
|
|
}
|
|
|
|
if (matches("clients", P)) {
|
|
return { type: "client", id: segments[1] };
|
|
}
|
|
|
|
if (matches("browser-sessions", P)) {
|
|
return { type: "browser-session", id: segments[1] };
|
|
}
|
|
|
|
if (matches("session", P)) {
|
|
return { type: "session", id: segments[1] };
|
|
}
|
|
|
|
return { type: "unknown", segments };
|
|
};
|