forked from jsnbuchanan/crowd-funder-for-time-pwa
fix: Fix onboard-meeting-members deep link with groupId.
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
"type-check": "tsc --noEmit",
|
"type-check": "tsc --noEmit",
|
||||||
"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: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": "./scripts/test-mobile.sh",
|
"test:mobile": "./scripts/test-mobile.sh",
|
||||||
"test:android": "node scripts/test-android.js",
|
"test:android": "node scripts/test-android.js",
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 type { DeepLinkError } from "../interfaces/deepLinks";
|
import type { DeepLinkError } from "../interfaces/deepLinks";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
@@ -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>);
|
||||||
@@ -198,15 +199,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
|
||||||
logger.error(
|
logger.error(
|
||||||
`[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)}`,
|
||||||
);
|
);
|
||||||
await this.router.replace({
|
await this.router.replace({
|
||||||
name: "deep-link-error",
|
name: "deep-link-error",
|
||||||
@@ -226,20 +234,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) {
|
||||||
logger.error(
|
logger.error(
|
||||||
`[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)}`,
|
||||||
);
|
);
|
||||||
// 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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];
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export default class OnboardMeetingMembersView extends Vue {
|
|||||||
try {
|
try {
|
||||||
// Identity creation should be handled by router guard, but keep as fallback for meeting setup
|
// Identity creation should be handled by router guard, but keep as fallback for meeting setup
|
||||||
if (!this.activeDid) {
|
if (!this.activeDid) {
|
||||||
logger.info(
|
this.$logAndConsole(
|
||||||
"[OnboardMeetingMembersView] No active DID found, creating identity as fallback for meeting setup",
|
"[OnboardMeetingMembersView] No active DID found, creating identity as fallback for meeting setup",
|
||||||
);
|
);
|
||||||
this.activeDid = await generateSaveAndActivateIdentity();
|
this.activeDid = await generateSaveAndActivateIdentity();
|
||||||
|
|||||||
Reference in New Issue
Block a user