All checks were successful
Podman Rootless Demo / test-backend (push) Has been skipped
Podman Rootless Demo / test-frontend (push) Has been skipped
Podman Rootless Demo / build-backend (push) Has been skipped
Podman Rootless Demo / build-frontend (push) Successful in 9m4s
Podman Rootless Demo / deploy-prod (push) Successful in 55s
120 lines
No EOL
3.6 KiB
TypeScript
120 lines
No EOL
3.6 KiB
TypeScript
'use client';
|
|
|
|
import type { UserProfile, SPFPassport } from './auth/types';
|
|
|
|
/**
|
|
* WASM module interface with proper TypeScript typing
|
|
*/
|
|
interface PassportWASM {
|
|
parse_spf_file(data: Uint8Array, password: string): Promise<SPFPassport>;
|
|
get_profiles_from_passport(data: Uint8Array, password: string): Promise<UserProfile[]>;
|
|
validate_spf_signature(data: Uint8Array, signature: Uint8Array): Promise<boolean>;
|
|
}
|
|
|
|
/**
|
|
* WASM loader class for managing the WASM module
|
|
*/
|
|
export class PassportWASMLoader {
|
|
private module: PassportWASM | null = null;
|
|
private isLoading: boolean = false;
|
|
private loadPromise: Promise<PassportWASM> | null = null;
|
|
|
|
/**
|
|
* Initialize the WASM module
|
|
*/
|
|
async init(): Promise<PassportWASM> {
|
|
if (this.module) {
|
|
return this.module;
|
|
}
|
|
|
|
if (this.loadPromise) {
|
|
return this.loadPromise;
|
|
}
|
|
|
|
this.isLoading = true;
|
|
this.loadPromise = this.loadWASMModule();
|
|
|
|
try {
|
|
this.module = await this.loadPromise;
|
|
return this.module;
|
|
} catch (error) {
|
|
this.loadPromise = null;
|
|
this.isLoading = false;
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load the WASM module dynamically
|
|
*/
|
|
private async loadWASMModule(): Promise<PassportWASM> {
|
|
if (typeof window === 'undefined') {
|
|
throw new Error('WASM module can only be loaded in browser environment');
|
|
}
|
|
|
|
try {
|
|
// Dynamically import the WASM bindings
|
|
// With bundler target, the module is automatically initialized on import
|
|
// but we need to ensure the WASM memory is ready before calling functions
|
|
const wasmModule = await import('./wasm-pkg/sharenet_passport_wasm');
|
|
|
|
// Test that the WASM module is properly initialized by checking if
|
|
// the wasm memory is accessible through a simple property access
|
|
// This ensures the WASM module is fully loaded before we use it
|
|
if (!wasmModule || typeof wasmModule.parse_spf_file !== 'function') {
|
|
throw new Error('WASM module exports not properly loaded');
|
|
}
|
|
|
|
// Create wrapper functions with proper typing
|
|
const wasmWrapper: PassportWASM = {
|
|
parse_spf_file: async (data: Uint8Array, password: string): Promise<SPFPassport> => {
|
|
const result = wasmModule.parse_spf_file(data, password);
|
|
// The WASM function returns a JsValue that we need to convert
|
|
// For now, we'll assume it returns the correct structure
|
|
return result as unknown as SPFPassport;
|
|
},
|
|
|
|
get_profiles_from_passport: async (data: Uint8Array, password: string): Promise<UserProfile[]> => {
|
|
const result = wasmModule.get_profiles_from_passport(data, password);
|
|
return result as unknown as UserProfile[];
|
|
},
|
|
|
|
validate_spf_signature: async (data: Uint8Array, signature: Uint8Array): Promise<boolean> => {
|
|
return wasmModule.validate_spf_signature(data, signature);
|
|
},
|
|
};
|
|
|
|
return wasmWrapper;
|
|
} catch (error) {
|
|
console.error('Failed to load WASM module:', error);
|
|
throw new Error(`Failed to load WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the module is loaded
|
|
*/
|
|
isLoaded(): boolean {
|
|
return this.module !== null;
|
|
}
|
|
|
|
/**
|
|
* Check if the module is currently loading
|
|
*/
|
|
getIsLoading(): boolean {
|
|
return this.isLoading;
|
|
}
|
|
|
|
/**
|
|
* Get the loaded module (throws if not loaded)
|
|
*/
|
|
getModule(): PassportWASM {
|
|
if (!this.module) {
|
|
throw new Error('WASM module not loaded. Call init() first.');
|
|
}
|
|
return this.module;
|
|
}
|
|
}
|
|
|
|
// Create a singleton instance
|
|
export const passportWASM = new PassportWASMLoader(); |