Browse Source

fix: Fix onboard-meeting-members deep link with groupId.

master-patch
Trent Larson 3 days ago
parent
commit
de476210c5
  1. 1
      package.json
  2. 28
      src/interfaces/deepLinks.ts
  3. 30
      src/services/deepLinks.ts
  4. 4
      src/views/DeepLinkErrorView.vue
  5. 3
      src/views/OnboardMeetingMembersView.vue

1
package.json

@ -14,6 +14,7 @@
"prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js",
"test:all": "npm run test:prerequisites && npm run build && npm run test:web && npm run test:mobile", "test:all": "npm run test:prerequisites && npm run build && npm run test:web && npm run test:mobile",
"test:prerequisites": "node scripts/check-prerequisites.js", "test:prerequisites": "node scripts/check-prerequisites.js",
"test:all": "npm run lint && tsc && npm run test:web && npm run test:mobile && ./scripts/test-safety-check.sh && echo '\n\n\nGotta add the performance tests'",
"test:web": "npx playwright test -c playwright.config-local.ts --trace on", "test:web": "npx playwright test -c playwright.config-local.ts --trace on",
"test:mobile": "npm run build:capacitor && npm run test:android && npm run test:ios", "test:mobile": "npm run build:capacitor && npm run test:android && npm run test:ios",
"test:android": "node scripts/test-android.js", "test:android": "node scripts/test-android.js",

28
src/interfaces/deepLinks.ts

@ -28,7 +28,7 @@
import { z } from "zod"; import { z } from "zod";
// Parameter validation schemas for each route type // Parameter validation schemas for each route type
export const deepLinkSchemas = { export const deepLinkPathSchemas = {
claim: z.object({ claim: z.object({
id: z.string(), id: z.string(),
}), }),
@ -60,7 +60,7 @@ export const deepLinkSchemas = {
jwt: z.string().optional(), jwt: z.string().optional(),
}), }),
"onboard-meeting-members": z.object({ "onboard-meeting-members": z.object({
id: z.string(), groupId: z.string(),
}), }),
project: z.object({ project: z.object({
id: z.string(), id: z.string(),
@ -70,6 +70,17 @@ export const deepLinkSchemas = {
}), }),
}; };
export const deepLinkQuerySchemas = {
"onboard-meeting-members": z.object({
password: z.string(),
}),
};
// Add a union type of all valid route paths
export const VALID_DEEP_LINK_ROUTES = Object.keys(
deepLinkPathSchemas,
) as readonly (keyof typeof deepLinkPathSchemas)[];
// Create a type from the array // Create a type from the array
export type DeepLinkRoute = (typeof VALID_DEEP_LINK_ROUTES)[number]; export type DeepLinkRoute = (typeof VALID_DEEP_LINK_ROUTES)[number];
@ -80,14 +91,13 @@ export const baseUrlSchema = z.object({
queryParams: z.record(z.string()).optional(), queryParams: z.record(z.string()).optional(),
}); });
// Add a union type of all valid route paths // export type DeepLinkPathParams = {
export const VALID_DEEP_LINK_ROUTES = Object.keys( // [K in keyof typeof deepLinkPathSchemas]: z.infer<(typeof deepLinkPathSchemas)[K]>;
deepLinkSchemas, // };
) as readonly (keyof typeof deepLinkSchemas)[];
export type DeepLinkParams = { // export type DeepLinkQueryParams = {
[K in keyof typeof deepLinkSchemas]: z.infer<(typeof deepLinkSchemas)[K]>; // [K in keyof typeof deepLinkQuerySchemas]: z.infer<(typeof deepLinkQuerySchemas)[K]>;
}; // };
export interface DeepLinkError extends Error { export interface DeepLinkError extends Error {
code: string; code: string;

30
src/services/deepLinks.ts

@ -47,10 +47,11 @@ import { Router } from "vue-router";
import { z } from "zod"; import { z } from "zod";
import { import {
deepLinkSchemas, deepLinkPathSchemas,
baseUrlSchema, baseUrlSchema,
routeSchema, routeSchema,
DeepLinkRoute, DeepLinkRoute,
deepLinkQuerySchemas,
} from "../interfaces/deepLinks"; } from "../interfaces/deepLinks";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import type { DeepLinkError } from "../interfaces/deepLinks"; import type { DeepLinkError } from "../interfaces/deepLinks";
@ -74,7 +75,7 @@ function getFirstKeyFromZodObject(
* because "router.replace" expects the right parameter name for the route. * because "router.replace" expects the right parameter name for the route.
*/ */
export const ROUTE_MAP: Record<string, { name: string; paramKey?: string }> = export const ROUTE_MAP: Record<string, { name: string; paramKey?: string }> =
Object.entries(deepLinkSchemas).reduce( Object.entries(deepLinkPathSchemas).reduce(
(acc, [routeName, schema]) => { (acc, [routeName, schema]) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const paramKey = getFirstKeyFromZodObject(schema as z.ZodObject<any>); const paramKey = getFirstKeyFromZodObject(schema as z.ZodObject<any>);
@ -199,16 +200,22 @@ export class DeepLinkHandler {
} }
// Continue with parameter validation as before... // Continue with parameter validation as before...
const schema = deepLinkSchemas[path as keyof typeof deepLinkSchemas]; const pathSchema = deepLinkPathSchemas[path as keyof typeof deepLinkPathSchemas];
const querySchema = deepLinkQuerySchemas[path as keyof typeof deepLinkQuerySchemas];
let validatedParams; let validatedPathParams: Record<string, string> = {};
let validatedQueryParams: Record<string, string> = {};
try { try {
validatedParams = await schema.parseAsync(params); if (pathSchema) {
validatedPathParams = await pathSchema.parseAsync(params);
}
if (querySchema) {
validatedQueryParams = await querySchema.parseAsync(query);
}
} catch (error) { } catch (error) {
// For parameter validation errors, provide specific error feedback // For parameter validation errors, provide specific error feedback
logConsoleAndDb( logConsoleAndDb(
`[DeepLink] Invalid parameters for route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`, `[DeepLink] Invalid parameters for route name ${routeName} for path: ${path} ... with error: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`,
true,
); );
await this.router.replace({ await this.router.replace({
name: "deep-link-error", name: "deep-link-error",
@ -228,21 +235,22 @@ export class DeepLinkHandler {
try { try {
await this.router.replace({ await this.router.replace({
name: routeName, name: routeName,
params: validatedParams, params: validatedPathParams,
query: validatedQueryParams
}); });
} catch (error) { } catch (error) {
logConsoleAndDb( logConsoleAndDb(
`[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedParams)}`, `[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedPathParams)} ... and query: ${JSON.stringify(validatedQueryParams)}`,
true,
); );
// For parameter validation errors, provide specific error feedback // For parameter validation errors, provide specific error feedback
await this.router.replace({ await this.router.replace({
name: "deep-link-error", name: "deep-link-error",
params: validatedParams, params: validatedPathParams,
query: { query: {
originalPath: path, originalPath: path,
errorCode: "ROUTING_ERROR", errorCode: "ROUTING_ERROR",
errorMessage: `Error routing to ${routeName}: ${JSON.stringify(error)}`, errorMessage: `Error routing to ${routeName}: ${JSON.stringify(error)}`,
...validatedQueryParams,
}, },
}); });
} }

4
src/views/DeepLinkErrorView.vue

@ -47,7 +47,7 @@ import { computed, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { import {
VALID_DEEP_LINK_ROUTES, VALID_DEEP_LINK_ROUTES,
deepLinkSchemas, deepLinkPathSchemas,
} from "../interfaces/deepLinks"; } from "../interfaces/deepLinks";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@ -56,7 +56,7 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
// an object with the route as the key and the first param name as the value // an object with the route as the key and the first param name as the value
const deepLinkSchemaKeys = Object.fromEntries( const deepLinkSchemaKeys = Object.fromEntries(
Object.entries(deepLinkSchemas).map(([route, schema]) => { Object.entries(deepLinkPathSchemas).map(([route, schema]) => {
const param = Object.keys(schema.shape)[0]; const param = Object.keys(schema.shape)[0];
return [route, param]; return [route, param];
}), }),

3
src/views/OnboardMeetingMembersView.vue

@ -117,6 +117,9 @@ export default class OnboardMeetingMembersView extends Vue {
this.isRegistered = settings.isRegistered || false; this.isRegistered = settings.isRegistered || false;
try { try {
if (!this.activeDid) { if (!this.activeDid) {
logConsoleAndDb(
"[OnboardMeetingMembersView] No active DID found, creating identity as fallback for meeting setup",
);
this.activeDid = await generateSaveAndActivateIdentity(); this.activeDid = await generateSaveAndActivateIdentity();
this.isRegistered = false; this.isRegistered = false;
} }

Loading…
Cancel
Save