forked from jsnbuchanan/crowd-funder-for-time-pwa
feat(deepLinks): implement comprehensive deep linking system
- Add type-safe deep link parameter validation using Zod - Implement consistent error handling across all deep link routes - Add support for query parameters in deep links - Create comprehensive deep linking documentation - Add logging for deep link operations Security: - Validate all deep link parameters before processing - Sanitize and type-check query parameters - Add error boundaries around deep link handling - Implement route-specific parameter validation Testing: - Add parameter validation tests - Add error handling tests - Test query parameter support
This commit is contained in:
@@ -49,6 +49,8 @@ import { App } from "./lib/capacitor/app";
|
||||
import router from "./router";
|
||||
import { handleApiError } from "./services/api";
|
||||
import { AxiosError } from "axios";
|
||||
import { DeepLinkHandler } from "./services/deepLinks";
|
||||
import { logConsoleAndDb } from "./db";
|
||||
|
||||
console.log("[Capacitor] Starting initialization");
|
||||
console.log("[Capacitor] Platform:", process.env.VITE_PLATFORM);
|
||||
@@ -62,6 +64,8 @@ window.addEventListener("unhandledrejection", (event) => {
|
||||
}
|
||||
});
|
||||
|
||||
const deepLinkHandler = new DeepLinkHandler(router);
|
||||
|
||||
/**
|
||||
* Handles deep link routing for the application
|
||||
* Processes URLs in the format timesafari://<route>/<param>
|
||||
@@ -80,56 +84,11 @@ window.addEventListener("unhandledrejection", (event) => {
|
||||
*/
|
||||
const handleDeepLink = async (data: { url: string }) => {
|
||||
try {
|
||||
console.log("[Capacitor Deep Link] START Handler");
|
||||
console.log("[Capacitor Deep Link] Received URL:", data.url);
|
||||
|
||||
await router.isReady();
|
||||
|
||||
const parts = data.url.split("://");
|
||||
if (parts.length !== 2) {
|
||||
throw new Error("Invalid URL format");
|
||||
}
|
||||
|
||||
const path = parts[1];
|
||||
console.log("[Capacitor Deep Link] Parsed path:", path);
|
||||
|
||||
// Define supported parameterized routes and their regex patterns
|
||||
const paramRoutes = {
|
||||
"claim-add-raw": /^claim-add-raw\/(.+)$/,
|
||||
"claim-cert": /^claim-cert\/(.+)$/,
|
||||
claim: /^claim\/(.+)$/,
|
||||
"confirm-gift": /^confirm-gift\/(.+)$/,
|
||||
"contact-edit": /^contact-edit\/(.+)$/,
|
||||
"contact-import": /^contact-import\/(.+)$/,
|
||||
did: /^did\/(.+)$/,
|
||||
"invite-one-accept": /^invite-one-accept\/(.+)$/,
|
||||
"offer-details": /^offer-details\/(.+)$/,
|
||||
project: /^project\/(.+)$/,
|
||||
"user-profile": /^user-profile\/(.+)$/,
|
||||
};
|
||||
|
||||
// Match route pattern and extract parameter
|
||||
for (const [routeName, pattern] of Object.entries(paramRoutes)) {
|
||||
const match = path.match(pattern);
|
||||
if (match) {
|
||||
console.log(
|
||||
`[Capacitor Deep Link] Matched route: ${routeName}, param: ${match[1]}`,
|
||||
);
|
||||
await router.replace({
|
||||
name: routeName,
|
||||
params: { id: match[1] },
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Default fallback for non-parameterized routes
|
||||
await router.replace("/" + path);
|
||||
await deepLinkHandler.handleDeepLink(data.url);
|
||||
} catch (error) {
|
||||
console.error("[Capacitor Deep Link] Error:", error);
|
||||
if (error instanceof Error) {
|
||||
handleApiError({ message: error.message } as AxiosError, "deep-link");
|
||||
}
|
||||
logConsoleAndDb("[DeepLink] Error handling deep link: " + error, true);
|
||||
handleApiError(error, "deep-link");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user