- Hierarchical user/device identity system with HD key derivation - Dependency injection for AsyncStorage and Platform - Self-contained TypeScript declarations - Ed25519 keypairs managed by IdentityManager - Deterministic peer ID generation from BIP39 mnemonic
119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
/**
|
|
* Factory for creating identity manager instances
|
|
*/
|
|
|
|
import { LoggerComponent } from 'ior:gitea:gitea.metatrom.net:universal-components/logger@1.0.0';
|
|
import { AsyncStorageAdapter } from './implementations/AsyncStorageAdapter';
|
|
import { IdentityManager } from './implementations/IdentityManager';
|
|
import type {
|
|
IdentityConfig,
|
|
IIdentityFactory,
|
|
IIdentityManager,
|
|
IIdentityStorage,
|
|
} from './interfaces/IIdentity';
|
|
|
|
// Platform interface for dependency injection
|
|
interface IPlatform {
|
|
OS: string;
|
|
}
|
|
|
|
export class IdentityFactory implements IIdentityFactory {
|
|
private static instance?: IdentityFactory;
|
|
private identityManager?: IIdentityManager;
|
|
private storage?: IIdentityStorage;
|
|
private logger = new LoggerComponent('IdentityFactory');
|
|
private platform?: IPlatform;
|
|
private asyncStorage?: any;
|
|
|
|
private constructor(platform?: IPlatform, asyncStorage?: any) {
|
|
this.platform = platform;
|
|
this.asyncStorage = asyncStorage;
|
|
}
|
|
|
|
static getInstance(platform?: IPlatform, asyncStorage?: any): IdentityFactory {
|
|
if (!IdentityFactory.instance) {
|
|
IdentityFactory.instance = new IdentityFactory(platform, asyncStorage);
|
|
}
|
|
return IdentityFactory.instance;
|
|
}
|
|
|
|
create(config?: IdentityConfig): IIdentityManager {
|
|
// Use singleton pattern for identity manager
|
|
if (!this.identityManager) {
|
|
const storage = this.getStorage();
|
|
|
|
// Enhanced config with platform-specific device name provider
|
|
const enhancedConfig: IdentityConfig = {
|
|
...config,
|
|
deviceNameProvider: config?.deviceNameProvider || this.getDeviceNameProvider(),
|
|
};
|
|
|
|
this.identityManager = new IdentityManager(storage, enhancedConfig);
|
|
}
|
|
|
|
return this.identityManager;
|
|
}
|
|
|
|
private getStorage(): IIdentityStorage {
|
|
if (!this.storage) {
|
|
if (!this.asyncStorage) {
|
|
throw new Error('AsyncStorage not provided. Please provide AsyncStorage when creating the factory.');
|
|
}
|
|
// Use AsyncStorage for React Native
|
|
this.storage = new AsyncStorageAdapter(this.asyncStorage);
|
|
}
|
|
return this.storage;
|
|
}
|
|
|
|
private getDeviceNameProvider(): () => Promise<string> {
|
|
return async () => {
|
|
try {
|
|
// Try to use react-native-device-info if available
|
|
const DeviceInfo = require('react-native-device-info').default;
|
|
if (DeviceInfo?.getDeviceName) {
|
|
const name = await DeviceInfo.getDeviceName();
|
|
return name || this.getFallbackDeviceName();
|
|
}
|
|
} catch (_error) {
|
|
// Module not available, use fallback
|
|
this.logger.debug('react-native-device-info not available, using fallback device name');
|
|
}
|
|
|
|
return this.getFallbackDeviceName();
|
|
};
|
|
}
|
|
|
|
private getFallbackDeviceName(): string {
|
|
const platform = this.platform?.OS || 'unknown';
|
|
const timestamp = Date.now().toString(36).substring(-4);
|
|
|
|
switch (platform) {
|
|
case 'ios':
|
|
return `iPhone-${timestamp}`;
|
|
case 'android':
|
|
return `Android-${timestamp}`;
|
|
default:
|
|
return `Device-${timestamp}`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset the singleton instance (useful for testing)
|
|
*/
|
|
static reset(): void {
|
|
if (IdentityFactory.instance?.identityManager) {
|
|
IdentityFactory.instance.identityManager = undefined;
|
|
}
|
|
IdentityFactory.instance = undefined;
|
|
}
|
|
}
|
|
|
|
// Export singleton instance creator with dependency injection
|
|
export const createIdentityManager = (
|
|
config?: IdentityConfig,
|
|
platform?: IPlatform,
|
|
asyncStorage?: any
|
|
): IIdentityManager => {
|
|
return IdentityFactory.getInstance(platform, asyncStorage).create(config);
|
|
};
|