forked from jsnbuchanan/crowd-funder-for-time-pwa
Fix InviteOneAcceptView migration fence; remove USE_DEXIE_DB dependency
- Remove USE_DEXIE_DB import from app.ts constants - Update InviteOneAcceptView to use PlatformServiceMixin pattern - Remove legacy Dexie database access code - Move WORKER_ONLY_DATABASE_IMPLEMENTATION.md to doc/ directory - Remerge changes in router/index.ts Fixes Electron build failure caused by missing USE_DEXIE_DB export.
This commit is contained in:
@@ -44,15 +44,41 @@
|
||||
*/
|
||||
|
||||
import { Router } from "vue-router";
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
deepLinkSchemas,
|
||||
baseUrlSchema,
|
||||
routeSchema,
|
||||
DeepLinkRoute,
|
||||
} from "../interfaces/deepLinks";
|
||||
// Legacy databaseUtil import removed - using logger instead
|
||||
import { logConsoleAndDb } from "../db/databaseUtil";
|
||||
import type { DeepLinkError } from "../interfaces/deepLinks";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
// Helper function to extract the first key from a Zod object schema
|
||||
function getFirstKeyFromZodObject(schema: z.ZodObject<any>): string | undefined {
|
||||
const shape = schema.shape;
|
||||
const keys = Object.keys(shape);
|
||||
return keys.length > 0 ? keys[0] : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps deep link routes to their corresponding Vue router names and optional parameter keys.
|
||||
*
|
||||
* It's an object where keys are the deep link routes and values are objects with 'name' and 'paramKey'.
|
||||
*
|
||||
* The paramKey is used to extract the parameter from the route path,
|
||||
* because "router.replace" expects the right parameter name for the route.
|
||||
*/
|
||||
export const ROUTE_MAP: Record<string, { name: string; paramKey?: string }> =
|
||||
Object.entries(deepLinkSchemas).reduce((acc, [routeName, schema]) => {
|
||||
const paramKey = getFirstKeyFromZodObject(schema as z.ZodObject<any>);
|
||||
acc[routeName] = {
|
||||
name: routeName,
|
||||
paramKey
|
||||
};
|
||||
return acc;
|
||||
}, {} as Record<string, { name: string; paramKey?: string }>);
|
||||
|
||||
/**
|
||||
* Handles processing and routing of deep links in the application.
|
||||
@@ -70,30 +96,7 @@ export class DeepLinkHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps deep link routes to their corresponding Vue router names and optional parameter keys.
|
||||
*
|
||||
* The paramKey is used to extract the parameter from the route path,
|
||||
* because "router.replace" expects the right parameter name for the route.
|
||||
* The default is "id".
|
||||
*/
|
||||
private readonly ROUTE_MAP: Record<
|
||||
string,
|
||||
{ name: string; paramKey?: string }
|
||||
> = {
|
||||
// note that similar lists are in src/interfaces/deepLinks.ts
|
||||
claim: { name: "claim" },
|
||||
"claim-add-raw": { name: "claim-add-raw" },
|
||||
"claim-cert": { name: "claim-cert" },
|
||||
"confirm-gift": { name: "confirm-gift" },
|
||||
"contact-import": { name: "contact-import", paramKey: "jwt" },
|
||||
did: { name: "did", paramKey: "did" },
|
||||
"invite-one-accept": { name: "invite-one-accept", paramKey: "jwt" },
|
||||
"onboard-meeting-members": { name: "onboard-meeting-members" },
|
||||
project: { name: "project" },
|
||||
"user-profile": { name: "user-profile" },
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses deep link URL into path, params and query components.
|
||||
* Validates URL structure using Zod schemas.
|
||||
*
|
||||
@@ -116,18 +119,9 @@ export class DeepLinkHandler {
|
||||
|
||||
const [path, queryString] = parts[1].split("?");
|
||||
const [routePath, ...pathParams] = path.split("/");
|
||||
// logger.info(
|
||||
// "[DeepLink] Debug:",
|
||||
// "Route Path:",
|
||||
// routePath,
|
||||
// "Path Params:",
|
||||
// pathParams,
|
||||
// "Query String:",
|
||||
// queryString,
|
||||
// );
|
||||
|
||||
// Validate route exists before proceeding
|
||||
if (!this.ROUTE_MAP[routePath]) {
|
||||
if (!ROUTE_MAP[routePath]) {
|
||||
throw {
|
||||
code: "INVALID_ROUTE",
|
||||
message: `Invalid route path: ${routePath}`,
|
||||
@@ -145,9 +139,14 @@ export class DeepLinkHandler {
|
||||
const params: Record<string, string> = {};
|
||||
if (pathParams) {
|
||||
// Now we know routePath exists in ROUTE_MAP
|
||||
const routeConfig = this.ROUTE_MAP[routePath];
|
||||
const routeConfig = ROUTE_MAP[routePath];
|
||||
params[routeConfig.paramKey ?? "id"] = pathParams.join("/");
|
||||
}
|
||||
|
||||
// logConsoleAndDb(
|
||||
// `[DeepLink] Debug: Route Path: ${routePath} Path Params: ${JSON.stringify(params)} Query String: ${JSON.stringify(query)}`,
|
||||
// false,
|
||||
// );
|
||||
return { path: routePath, params, query };
|
||||
}
|
||||
|
||||
@@ -171,60 +170,73 @@ export class DeepLinkHandler {
|
||||
try {
|
||||
// Validate route exists
|
||||
const validRoute = routeSchema.parse(path) as DeepLinkRoute;
|
||||
routeName = this.ROUTE_MAP[validRoute].name;
|
||||
routeName = ROUTE_MAP[validRoute].name;
|
||||
} catch (error) {
|
||||
// Log the invalid route attempt
|
||||
logger.error(`[DeepLink] Invalid route path: ${path}`);
|
||||
logConsoleAndDb(`[DeepLink] Invalid route path: ${path}`, true);
|
||||
|
||||
// Redirect to error page with information about the invalid link
|
||||
await this.router.replace({
|
||||
name: "deep-link-error",
|
||||
params,
|
||||
query: {
|
||||
originalPath: path,
|
||||
errorCode: "INVALID_ROUTE",
|
||||
message: `The link you followed (${path}) is not supported`,
|
||||
errorMessage: `The link you followed (${path}) is not supported`,
|
||||
...query,
|
||||
},
|
||||
});
|
||||
|
||||
throw {
|
||||
code: "INVALID_ROUTE",
|
||||
message: `Unsupported route: ${path}`,
|
||||
};
|
||||
// This previously threw an error but we're redirecting so there's no need.
|
||||
return;
|
||||
}
|
||||
|
||||
// Continue with parameter validation as before...
|
||||
const schema = deepLinkSchemas[path as keyof typeof deepLinkSchemas];
|
||||
|
||||
let validatedParams, validatedQuery;
|
||||
try {
|
||||
const validatedParams = await schema.parseAsync({
|
||||
...params,
|
||||
...query,
|
||||
});
|
||||
|
||||
await this.router.replace({
|
||||
name: routeName,
|
||||
params: validatedParams,
|
||||
query,
|
||||
});
|
||||
validatedParams = await schema.parseAsync(params);
|
||||
validatedQuery = await schema.parseAsync(query);
|
||||
} catch (error) {
|
||||
// For parameter validation errors, provide specific error feedback
|
||||
logConsoleAndDb(`[DeepLink] Invalid parameters for route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`, true);
|
||||
await this.router.replace({
|
||||
name: "deep-link-error",
|
||||
params,
|
||||
query: {
|
||||
originalPath: path,
|
||||
errorCode: "INVALID_PARAMETERS",
|
||||
message: `The link parameters are invalid: ${(error as Error).message}`,
|
||||
errorMessage: `The link parameters are invalid: ${(error as Error).message}`,
|
||||
...query,
|
||||
},
|
||||
});
|
||||
|
||||
throw {
|
||||
code: "INVALID_PARAMETERS",
|
||||
message: (error as Error).message,
|
||||
details: error,
|
||||
params: params,
|
||||
query: query,
|
||||
};
|
||||
// This previously threw an error but we're redirecting so there's no need.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.router.replace({
|
||||
name: routeName,
|
||||
params: validatedParams,
|
||||
query: validatedQuery,
|
||||
});
|
||||
} catch (error) {
|
||||
logConsoleAndDb(`[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedParams)} ... and validated query: ${JSON.stringify(validatedQuery)}`, true);
|
||||
// For parameter validation errors, provide specific error feedback
|
||||
await this.router.replace({
|
||||
name: "deep-link-error",
|
||||
params: validatedParams,
|
||||
query: {
|
||||
originalPath: path,
|
||||
errorCode: "ROUTING_ERROR",
|
||||
errorMessage: `Error routing to ${routeName}: ${(JSON.stringify(error))}`,
|
||||
...validatedQuery,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,7 +248,6 @@ export class DeepLinkHandler {
|
||||
*/
|
||||
async handleDeepLink(url: string): Promise<void> {
|
||||
try {
|
||||
logger.info("[DeepLink] Processing URL: " + url);
|
||||
const { path, params, query } = this.parseDeepLink(url);
|
||||
// Ensure params is always a Record<string,string> by converting undefined to empty string
|
||||
const sanitizedParams = Object.fromEntries(
|
||||
@@ -245,8 +256,9 @@ export class DeepLinkHandler {
|
||||
await this.validateAndRoute(path, sanitizedParams, query);
|
||||
} catch (error) {
|
||||
const deepLinkError = error as DeepLinkError;
|
||||
logger.error(
|
||||
`[DeepLink] Error (${deepLinkError.code}): ${deepLinkError.message}`,
|
||||
logConsoleAndDb(
|
||||
`[DeepLink] Error (${deepLinkError.code}): ${deepLinkError.details}`,
|
||||
true,
|
||||
);
|
||||
|
||||
throw {
|
||||
|
||||
Reference in New Issue
Block a user