@sudobility/di 1.5.0 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -39
- package/dist/mocks/firebase.mock.d.ts +109 -0
- package/dist/mocks/firebase.mock.d.ts.map +1 -0
- package/dist/mocks/firebase.mock.js +322 -0
- package/dist/mocks/firebase.mock.js.map +1 -0
- package/dist/mocks/index.d.ts +2 -1
- package/dist/mocks/index.d.ts.map +1 -1
- package/dist/mocks/index.js +2 -1
- package/dist/mocks/index.js.map +1 -1
- package/dist/mocks/network.mock.d.ts +37 -0
- package/dist/mocks/network.mock.d.ts.map +1 -1
- package/dist/mocks/network.mock.js +88 -0
- package/dist/mocks/network.mock.js.map +1 -1
- package/dist/rn/firebase/firebase.rn.d.ts +19 -0
- package/dist/rn/firebase/firebase.rn.d.ts.map +1 -0
- package/dist/rn/firebase/firebase.rn.js +318 -0
- package/dist/rn/firebase/firebase.rn.js.map +1 -0
- package/dist/rn/index.d.ts +21 -5
- package/dist/rn/index.d.ts.map +1 -1
- package/dist/rn/index.js +20 -5
- package/dist/rn/index.js.map +1 -1
- package/dist/web/firebase/firebase.web.d.ts +3 -0
- package/dist/web/firebase/firebase.web.d.ts.map +1 -1
- package/dist/web/firebase/firebase.web.js +14 -0
- package/dist/web/firebase/firebase.web.js.map +1 -1
- package/dist/web/index.d.ts +9 -1
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +8 -0
- package/dist/web/index.js.map +1 -1
- package/package.json +17 -1
package/README.md
CHANGED
|
@@ -1,67 +1,283 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @sudobility/di
|
|
2
2
|
|
|
3
|
-
Platform-agnostic dependency injection
|
|
3
|
+
Platform-agnostic dependency injection for React and React Native with automatic platform detection.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
This library provides
|
|
7
|
+
This library provides unified DI services that work identically on Web and React Native. The bundler automatically selects the correct platform implementation, so you write the same code for both platforms.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
11
|
+
- **Unified API**: Same code works on Web and React Native
|
|
12
|
+
- **Automatic Platform Detection**: Bundler selects correct implementation
|
|
13
|
+
- **TypeScript First**: Fully typed interfaces and implementations
|
|
14
|
+
- **Lazy Loading**: Native modules loaded only when used
|
|
15
|
+
- **Singleton Management**: Built-in service lifecycle management
|
|
16
|
+
- **Modular**: Import only what you need
|
|
16
17
|
|
|
17
18
|
## Installation
|
|
18
19
|
|
|
19
20
|
```bash
|
|
20
|
-
npm install @
|
|
21
|
+
npm install @sudobility/di
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
### Optional Peer Dependencies
|
|
25
|
+
|
|
26
|
+
**Web:**
|
|
27
|
+
```bash
|
|
28
|
+
npm install firebase
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**React Native:**
|
|
32
|
+
```bash
|
|
33
|
+
npm install @react-native-async-storage/async-storage
|
|
34
|
+
npm install @react-native-community/netinfo
|
|
35
|
+
npm install @react-native-firebase/app @react-native-firebase/analytics
|
|
36
|
+
npm install @react-native-firebase/remote-config @react-native-firebase/messaging
|
|
37
|
+
npm install @notifee/react-native
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### 1. Initialize Services
|
|
24
43
|
|
|
25
44
|
```typescript
|
|
45
|
+
// main.tsx or App.tsx
|
|
26
46
|
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
47
|
+
initializeStorageService,
|
|
48
|
+
initializeNetworkService,
|
|
49
|
+
initializeFirebaseService,
|
|
50
|
+
} from '@sudobility/di';
|
|
51
|
+
|
|
52
|
+
// Call before rendering app
|
|
53
|
+
initializeStorageService();
|
|
54
|
+
initializeNetworkService();
|
|
55
|
+
initializeFirebaseService(firebaseConfig);
|
|
37
56
|
```
|
|
38
57
|
|
|
39
|
-
|
|
58
|
+
### 2. Use Services
|
|
40
59
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
60
|
+
```typescript
|
|
61
|
+
import {
|
|
62
|
+
getStorageService,
|
|
63
|
+
getNetworkService,
|
|
64
|
+
getFirebaseService,
|
|
65
|
+
networkClient,
|
|
66
|
+
} from '@sudobility/di';
|
|
67
|
+
|
|
68
|
+
// Storage
|
|
69
|
+
const storage = getStorageService();
|
|
70
|
+
await storage.setItem('token', 'abc123');
|
|
71
|
+
const token = await storage.getItem('token');
|
|
72
|
+
|
|
73
|
+
// Network requests
|
|
74
|
+
const response = await networkClient.get<User>('/api/user');
|
|
75
|
+
|
|
76
|
+
// Network status
|
|
77
|
+
const network = getNetworkService();
|
|
78
|
+
const isOnline = network.isOnline();
|
|
79
|
+
|
|
80
|
+
// Firebase
|
|
81
|
+
const firebase = getFirebaseService();
|
|
82
|
+
firebase.analytics.logEvent('screen_view', { screen: 'Home' });
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
45
86
|
|
|
46
87
|
### Storage
|
|
47
|
-
- `StorageProvider` - Storage abstraction
|
|
48
|
-
- `PlatformStorage` - Basic storage interface
|
|
49
|
-
- `StorageService` - Enhanced storage service
|
|
50
88
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
89
|
+
```typescript
|
|
90
|
+
import { getStorageService, storage } from '@sudobility/di';
|
|
91
|
+
|
|
92
|
+
const storageService = getStorageService();
|
|
93
|
+
|
|
94
|
+
// Basic operations
|
|
95
|
+
await storageService.setItem('key', 'value');
|
|
96
|
+
const value = await storageService.getItem('key');
|
|
97
|
+
await storageService.removeItem('key');
|
|
98
|
+
await storageService.clear();
|
|
99
|
+
const keys = await storageService.getAllKeys();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Network Requests
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { networkClient } from '@sudobility/di';
|
|
106
|
+
|
|
107
|
+
// GET
|
|
108
|
+
const response = await networkClient.get<User>('/api/user');
|
|
109
|
+
if (response.ok) {
|
|
110
|
+
console.log(response.data);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// POST with body
|
|
114
|
+
const result = await networkClient.post<Result>('/api/submit', {
|
|
115
|
+
name: 'John',
|
|
116
|
+
email: 'john@example.com'
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// PUT and DELETE
|
|
120
|
+
await networkClient.put('/api/user/1', { name: 'Jane' });
|
|
121
|
+
await networkClient.delete('/api/user/1');
|
|
54
122
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
123
|
+
// With options
|
|
124
|
+
const response = await networkClient.get('/api/data', {
|
|
125
|
+
headers: { 'Authorization': 'Bearer token' },
|
|
126
|
+
timeout: 5000,
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Network Status
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { getNetworkService } from '@sudobility/di';
|
|
134
|
+
|
|
135
|
+
const network = getNetworkService();
|
|
136
|
+
|
|
137
|
+
// Check connection
|
|
138
|
+
const isOnline = network.isOnline();
|
|
139
|
+
|
|
140
|
+
// Watch for changes
|
|
141
|
+
const unsubscribe = network.watchNetworkStatus((online) => {
|
|
142
|
+
console.log('Connection:', online ? 'Online' : 'Offline');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Cleanup when done
|
|
146
|
+
unsubscribe();
|
|
147
|
+
```
|
|
58
148
|
|
|
59
|
-
###
|
|
60
|
-
- Auth interfaces for various providers
|
|
149
|
+
### Firebase
|
|
61
150
|
|
|
62
|
-
|
|
63
|
-
|
|
151
|
+
```typescript
|
|
152
|
+
import { getFirebaseService } from '@sudobility/di';
|
|
153
|
+
|
|
154
|
+
const firebase = getFirebaseService();
|
|
155
|
+
|
|
156
|
+
// Analytics
|
|
157
|
+
firebase.analytics.logEvent('purchase', { item: 'premium', price: 9.99 });
|
|
158
|
+
firebase.analytics.setUserId('user123');
|
|
159
|
+
firebase.analytics.setUserProperties({ plan: 'pro' });
|
|
160
|
+
|
|
161
|
+
// Remote Config
|
|
162
|
+
await firebase.remoteConfig.fetchAndActivate();
|
|
163
|
+
const showFeature = firebase.remoteConfig.getValue('new_feature').asBoolean();
|
|
164
|
+
const apiUrl = firebase.remoteConfig.getValue('api_url').asString();
|
|
165
|
+
const maxItems = firebase.remoteConfig.getValue('max_items').asNumber();
|
|
166
|
+
|
|
167
|
+
// Messaging (FCM)
|
|
168
|
+
const granted = await firebase.messaging.requestPermission();
|
|
169
|
+
if (granted) {
|
|
170
|
+
const token = await firebase.messaging.getToken();
|
|
171
|
+
console.log('FCM Token:', token);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const unsubscribe = firebase.messaging.onMessage((message) => {
|
|
175
|
+
console.log('Push notification:', message.notification?.title);
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### React Native Only Services
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import {
|
|
183
|
+
getThemeService,
|
|
184
|
+
getNavigationService,
|
|
185
|
+
getNotificationService,
|
|
186
|
+
} from '@sudobility/di';
|
|
187
|
+
|
|
188
|
+
// Theme
|
|
189
|
+
const theme = getThemeService();
|
|
190
|
+
const isDark = theme.isDarkMode();
|
|
191
|
+
theme.applyTheme('dark'); // 'light' | 'dark' | 'system'
|
|
192
|
+
theme.watchSystemTheme((mode) => {
|
|
193
|
+
console.log('System theme:', mode);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Navigation (call setNavigationRef first in App.tsx)
|
|
197
|
+
const nav = getNavigationService();
|
|
198
|
+
nav.navigate('Profile', { userId: '123' });
|
|
199
|
+
nav.goBack();
|
|
200
|
+
nav.replace('Home');
|
|
201
|
+
|
|
202
|
+
// Notifications
|
|
203
|
+
const notifications = getNotificationService();
|
|
204
|
+
await notifications.requestPermission();
|
|
205
|
+
await notifications.showNotification('Hello', {
|
|
206
|
+
body: 'You have a new message',
|
|
207
|
+
data: { screen: 'inbox' }
|
|
208
|
+
});
|
|
209
|
+
await notifications.setBadgeCount(5);
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Import Paths
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Auto-detect platform (recommended)
|
|
216
|
+
import { ... } from '@sudobility/di';
|
|
217
|
+
|
|
218
|
+
// Explicit web imports
|
|
219
|
+
import { ... } from '@sudobility/di/web';
|
|
220
|
+
|
|
221
|
+
// Explicit React Native imports
|
|
222
|
+
import { ... } from '@sudobility/di/rn';
|
|
223
|
+
|
|
224
|
+
// Interfaces only (no implementations)
|
|
225
|
+
import type { ... } from '@sudobility/di/interfaces';
|
|
226
|
+
|
|
227
|
+
// Mocks for testing
|
|
228
|
+
import { MockStorageService, MockNetworkClient } from '@sudobility/di/mocks';
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Unified Exports
|
|
232
|
+
|
|
233
|
+
These exports work identically on both platforms:
|
|
234
|
+
|
|
235
|
+
| Export | Description |
|
|
236
|
+
|--------|-------------|
|
|
237
|
+
| `networkClient` | Pre-configured network client instance |
|
|
238
|
+
| `storage` | Basic storage instance |
|
|
239
|
+
| `advancedStorage` | Storage with TTL support |
|
|
240
|
+
| `getStorageService()` | Get storage service singleton |
|
|
241
|
+
| `getNetworkService()` | Get network service singleton |
|
|
242
|
+
| `getFirebaseService()` | Get Firebase service singleton |
|
|
243
|
+
| `initializeStorageService()` | Initialize storage singleton |
|
|
244
|
+
| `initializeNetworkService()` | Initialize network singleton |
|
|
245
|
+
| `initializeFirebaseService()` | Initialize Firebase singleton |
|
|
246
|
+
| `StorageService` | Storage service class |
|
|
247
|
+
| `NetworkService` | Network service class |
|
|
248
|
+
| `FirebaseService` | Firebase service class |
|
|
249
|
+
|
|
250
|
+
## Platform-Specific Exports
|
|
251
|
+
|
|
252
|
+
### Web Only
|
|
253
|
+
- `WebStorageService`, `WebNetworkService`, `WebFirebaseService`
|
|
254
|
+
- `webStorage`, `webNetworkClient`
|
|
255
|
+
- `WebUINavigationService`
|
|
256
|
+
|
|
257
|
+
### React Native Only
|
|
258
|
+
- `RNStorageService`, `RNNetworkService`, `RNFirebaseService`
|
|
259
|
+
- `rnStorage`, `rnNetworkClient`
|
|
260
|
+
- `getThemeService()`, `getNavigationService()`, `getNotificationService()`
|
|
261
|
+
- `RNThemeService`, `RNNavigationService`, `RNNotificationService`
|
|
262
|
+
|
|
263
|
+
## Testing with Mocks
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
import {
|
|
267
|
+
MockStorageService,
|
|
268
|
+
MockNetworkClient,
|
|
269
|
+
MockAnalyticsClient,
|
|
270
|
+
} from '@sudobility/di/mocks';
|
|
271
|
+
|
|
272
|
+
// In your tests
|
|
273
|
+
const mockStorage = new MockStorageService();
|
|
274
|
+
await mockStorage.setItem('key', 'value');
|
|
275
|
+
expect(await mockStorage.getItem('key')).toBe('value');
|
|
276
|
+
|
|
277
|
+
const mockNetwork = new MockNetworkClient();
|
|
278
|
+
// Configure mock responses...
|
|
279
|
+
```
|
|
64
280
|
|
|
65
281
|
## License
|
|
66
282
|
|
|
67
|
-
MIT
|
|
283
|
+
MIT
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { AnalyticsService, RemoteConfigService, RemoteConfigValue, FCMService, FCMMessage, FCMPermissionState, FirebaseService, FirebaseConfig, FirebaseInitOptions } from '../web/firebase/firebase.interface.js';
|
|
2
|
+
export interface RecordedFirebaseAnalyticsEvent {
|
|
3
|
+
type: 'event' | 'userProperty' | 'userId';
|
|
4
|
+
name?: string;
|
|
5
|
+
parameters?: Record<string, unknown>;
|
|
6
|
+
properties?: Record<string, string>;
|
|
7
|
+
userId?: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class MockAnalyticsService implements AnalyticsService {
|
|
11
|
+
private events;
|
|
12
|
+
private supported;
|
|
13
|
+
private currentUserId;
|
|
14
|
+
private userProperties;
|
|
15
|
+
logEvent(eventName: string, parameters?: Record<string, unknown>): void;
|
|
16
|
+
setUserProperties(properties: Record<string, string>): void;
|
|
17
|
+
setUserId(userId: string): void;
|
|
18
|
+
isSupported(): boolean;
|
|
19
|
+
setSupported(supported: boolean): void;
|
|
20
|
+
getEvents(): RecordedFirebaseAnalyticsEvent[];
|
|
21
|
+
getEventsByType(type: 'event' | 'userProperty' | 'userId'): RecordedFirebaseAnalyticsEvent[];
|
|
22
|
+
getEventsByName(name: string): RecordedFirebaseAnalyticsEvent[];
|
|
23
|
+
getUserId(): string | null;
|
|
24
|
+
getUserProperties(): Record<string, string>;
|
|
25
|
+
reset(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare class MockRemoteConfigValue implements RemoteConfigValue {
|
|
28
|
+
private value;
|
|
29
|
+
private source;
|
|
30
|
+
constructor(value: string, source?: 'static' | 'default' | 'remote');
|
|
31
|
+
asBoolean(): boolean;
|
|
32
|
+
asString(): string;
|
|
33
|
+
asNumber(): number;
|
|
34
|
+
getSource(): 'static' | 'default' | 'remote';
|
|
35
|
+
}
|
|
36
|
+
export declare class MockRemoteConfigService implements RemoteConfigService {
|
|
37
|
+
private configs;
|
|
38
|
+
private supported;
|
|
39
|
+
private fetchDelay;
|
|
40
|
+
private fetchShouldFail;
|
|
41
|
+
private fetchError;
|
|
42
|
+
fetchAndActivate(): Promise<boolean>;
|
|
43
|
+
getValue(key: string): RemoteConfigValue;
|
|
44
|
+
getAll(): Record<string, RemoteConfigValue>;
|
|
45
|
+
isSupported(): boolean;
|
|
46
|
+
setSupported(supported: boolean): void;
|
|
47
|
+
setConfig(key: string, value: string, source?: 'static' | 'default' | 'remote'): void;
|
|
48
|
+
setConfigs(configs: Record<string, string>): void;
|
|
49
|
+
setFetchDelay(delay: number): void;
|
|
50
|
+
setFetchShouldFail(shouldFail: boolean, error?: Error): void;
|
|
51
|
+
clearConfig(key: string): void;
|
|
52
|
+
reset(): void;
|
|
53
|
+
}
|
|
54
|
+
export interface RecordedFCMEvent {
|
|
55
|
+
type: 'permissionRequest' | 'getToken' | 'deleteToken' | 'messageReceived';
|
|
56
|
+
token?: string | null;
|
|
57
|
+
message?: FCMMessage;
|
|
58
|
+
timestamp: number;
|
|
59
|
+
}
|
|
60
|
+
export declare class MockFCMService implements FCMService {
|
|
61
|
+
private events;
|
|
62
|
+
private supported;
|
|
63
|
+
private permissionStatus;
|
|
64
|
+
private mockToken;
|
|
65
|
+
private messageListeners;
|
|
66
|
+
private permissionRequestDelay;
|
|
67
|
+
private tokenRequestDelay;
|
|
68
|
+
private shouldFailPermission;
|
|
69
|
+
private shouldFailToken;
|
|
70
|
+
requestPermission(): Promise<boolean>;
|
|
71
|
+
getToken(): Promise<string | null>;
|
|
72
|
+
deleteToken(): Promise<boolean>;
|
|
73
|
+
onMessage(callback: (message: FCMMessage) => void): () => void;
|
|
74
|
+
isSupported(): boolean;
|
|
75
|
+
getPermissionStatus(): FCMPermissionState;
|
|
76
|
+
setSupported(supported: boolean): void;
|
|
77
|
+
setToken(token: string | null): void;
|
|
78
|
+
setPermissionGranted(granted: boolean): void;
|
|
79
|
+
setPermissionRequestDelay(delay: number): void;
|
|
80
|
+
setTokenRequestDelay(delay: number): void;
|
|
81
|
+
setShouldFailPermission(shouldFail: boolean): void;
|
|
82
|
+
setShouldFailToken(shouldFail: boolean): void;
|
|
83
|
+
simulateMessage(message: FCMMessage): void;
|
|
84
|
+
getEvents(): RecordedFCMEvent[];
|
|
85
|
+
getEventsByType(type: 'permissionRequest' | 'getToken' | 'deleteToken' | 'messageReceived'): RecordedFCMEvent[];
|
|
86
|
+
getListenerCount(): number;
|
|
87
|
+
reset(): void;
|
|
88
|
+
}
|
|
89
|
+
export declare class MockFirebaseService implements FirebaseService {
|
|
90
|
+
analytics: MockAnalyticsService;
|
|
91
|
+
remoteConfig: MockRemoteConfigService;
|
|
92
|
+
messaging: MockFCMService;
|
|
93
|
+
private configured;
|
|
94
|
+
private developmentMode;
|
|
95
|
+
private config;
|
|
96
|
+
private options;
|
|
97
|
+
constructor(config?: FirebaseConfig, options?: FirebaseInitOptions);
|
|
98
|
+
isConfigured(): boolean;
|
|
99
|
+
isDevelopment(): boolean;
|
|
100
|
+
setConfigured(configured: boolean): void;
|
|
101
|
+
setDevelopmentMode(developmentMode: boolean): void;
|
|
102
|
+
getConfig(): FirebaseConfig | null;
|
|
103
|
+
getOptions(): FirebaseInitOptions | null;
|
|
104
|
+
reset(): void;
|
|
105
|
+
}
|
|
106
|
+
export declare function getMockFirebaseService(): MockFirebaseService;
|
|
107
|
+
export declare function initializeMockFirebaseService(config?: FirebaseConfig, options?: FirebaseInitOptions): MockFirebaseService;
|
|
108
|
+
export declare function resetMockFirebaseService(): void;
|
|
109
|
+
//# sourceMappingURL=firebase.mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase.mock.d.ts","sourceRoot":"","sources":["../../src/mocks/firebase.mock.ts"],"names":[],"mappings":"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"}
|