@ -1,44 +1,114 @@
/ * *
* @file Capacitor Platform Entry Point
* @description Initializes the application for Capacitor platform ( iOS / Android )
* @author Matthew Raymer
* @version 0.4 . 4
*
* Process Flow :
* 1 . Initialization
* - Logs start of initialization
* - Logs current platform
* - Initializes core application via main . common
*
* 2 . Error Handling Setup
* - Registers global unhandled promise rejection handler
* - Routes API errors to error handling system
*
* 3 . Deep Linking Configuration
* - Registers URL scheme handler ( timesafari : //)
* - Supports 11 parameterized routes :
* * claim - add - raw
* * claim - cert
* * claim
* * confirm - gift
* * contact - edit
* * contact - import
* * did
* * invite - one - accept
* * offer - details
* * project
* * userProfile
*
* 4 . Application Mounting
* - Mounts Vue application to DOM
* - Logs completion of mounting process
*
* Security Measures :
* - URL validation before processing
* - Type - safe error handling
* - Parameterized route pattern matching
* - Comprehensive error logging
*
* @example Deep Link Format
* timesafari : //<route>/<parameter>
* timesafari : //claim/01JMAAFZRNSRTQ0EBSD70A8E1H
* /
import { initializeApp } from "./main.common" ;
import { initializeApp } from "./main.common" ;
import { App } from "@capacitor/app" ;
import { App } from "@capacitor/app" ;
import router from "./router" ;
import router from "./router" ;
import { handleApiError } from "./services/api" ;
import { handleApiError } from "./services/api" ;
import { AxiosError } from "axios" ;
console . log ( "[Capacitor] Starting initialization" ) ;
console . log ( "[Capacitor] Starting initialization" ) ;
console . log ( "[Capacitor] Platform:" , process . env . VITE_PLATFORM ) ;
console . log ( "[Capacitor] Platform:" , process . env . VITE_PLATFORM ) ;
const app = initializeApp ( ) ;
const app = initializeApp ( ) ;
// Initialize API error handling
// Initialize API error handling for unhandled promise rejections
window . addEventListener ( "unhandledrejection" , ( event ) = > {
window . addEventListener ( "unhandledrejection" , ( event ) = > {
if ( event . reason ? . response ) {
if ( event . reason ? . response ) {
handleApiError ( event . reason , event . reason . config ? . url || "unknown" ) ;
handleApiError ( event . reason , event . reason . config ? . url || "unknown" ) ;
}
}
} ) ;
} ) ;
// Create reusable handler function
/ * *
* Handles deep link routing for the application
* Processes URLs in the format timesafari : //<route>/<param>
* Maps incoming deep links to corresponding router paths with parameters
*
* @param { Object } data - Deep link data object
* @param { string } data . url - The full deep link URL to process
* @returns { Promise < void > }
*
* @example
* // Handles URLs like:
* // timesafari://claim/01JMAAFZRNSRTQ0EBSD70A8E1H
* // timesafari://project/abc123
*
* @throws { Error } If URL format is invalid
* /
const handleDeepLink = async ( data : { url : string } ) = > {
const handleDeepLink = async ( data : { url : string } ) = > {
try {
try {
console . log ( "[Capacitor Deep Link] START Handler" ) ;
console . log ( "[Capacitor Deep Link] START Handler" ) ;
console . log ( "[Capacitor Deep Link] Received URL:" , data . url ) ;
console . log ( "[Capacitor Deep Link] Received URL:" , data . url ) ;
// Wait for router to be ready
await router . isReady ( ) ;
await router . isReady ( ) ;
// Parse the custom URL scheme
const parts = data . url . split ( "://" ) ;
const parts = data . url . split ( "://" ) ;
if ( parts . length !== 2 ) {
if ( parts . length !== 2 ) {
throw new Error ( "Invalid URL format" ) ;
throw new Error ( "Invalid URL format" ) ;
}
}
const path = parts [ 1 ] ; // This will be "claim/01JMAAFZRNSRTQ0EBSD70A8E1H"
const path = parts [ 1 ] ;
console . log ( "[Capacitor Deep Link] Parsed path:" , path ) ;
console . log ( "[Capacitor Deep Link] Parsed path:" , path ) ;
// Map parameterized routes
// Define supported parameterized routes and their regex pattern s
const paramRoutes = {
const paramRoutes = {
claim : /^claim\/(.+)$/ , // Updated pattern without leading slash
'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\/(.+)$/ ,
'userProfile' : /^userProfile\/(.+)$/
} ;
} ;
// Check if path matches any parameterized route
// Match route pattern and extract parameter
for ( const [ routeName , pattern ] of Object . entries ( paramRoutes ) ) {
for ( const [ routeName , pattern ] of Object . entries ( paramRoutes ) ) {
const match = path . match ( pattern ) ;
const match = path . match ( pattern ) ;
if ( match ) {
if ( match ) {
@ -53,14 +123,17 @@ const handleDeepLink = async (data: { url: string }) => {
}
}
}
}
// Default fallback for non-parameterized routes
await router . replace ( "/" + path ) ;
await router . replace ( "/" + path ) ;
} catch ( error ) {
} catch ( error ) {
console . error ( "[Capacitor Deep Link] Error:" , error ) ;
console . error ( "[Capacitor Deep Link] Error:" , error ) ;
handleApiError ( error , "deep-link" ) ;
if ( error instanceof Error ) {
handleApiError ( { message : error.message } as AxiosError , "deep-link" ) ;
}
}
}
} ;
} ;
// Register listene r
// Register deep link handler with Capacito r
App . addListener ( "appUrlOpen" , handleDeepLink ) ;
App . addListener ( "appUrlOpen" , handleDeepLink ) ;
console . log ( "[Capacitor] Mounting app" ) ;
console . log ( "[Capacitor] Mounting app" ) ;