react-achievements 3.2.1 → 3.4.0
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 +874 -1
- package/dist/index.d.ts +308 -4
- package/dist/index.js +1048 -19
- package/dist/index.js.map +1 -1
- package/dist/types/core/errors/AchievementErrors.d.ts +55 -0
- package/dist/types/core/storage/AsyncStorageAdapter.d.ts +48 -0
- package/dist/types/core/storage/IndexedDBStorage.d.ts +29 -0
- package/dist/types/core/storage/OfflineQueueStorage.d.ts +42 -0
- package/dist/types/core/storage/RestApiStorage.d.ts +20 -0
- package/dist/types/core/types.d.ts +13 -2
- package/dist/types/core/utils/dataExport.d.ts +34 -0
- package/dist/types/core/utils/dataImport.d.ts +50 -0
- package/dist/types/hooks/useSimpleAchievements.d.ts +12 -0
- package/dist/types/index.d.ts +9 -1
- package/dist/types/providers/AchievementProvider.d.ts +9 -2
- package/package.json +3 -1
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,15 @@ interface AchievementStorage {
|
|
|
51
51
|
setUnlockedAchievements(achievements: string[]): void;
|
|
52
52
|
clear(): void;
|
|
53
53
|
}
|
|
54
|
+
interface AsyncAchievementStorage {
|
|
55
|
+
getMetrics(): Promise<AchievementMetrics>;
|
|
56
|
+
setMetrics(metrics: AchievementMetrics): Promise<void>;
|
|
57
|
+
getUnlockedAchievements(): Promise<string[]>;
|
|
58
|
+
setUnlockedAchievements(achievements: string[]): Promise<void>;
|
|
59
|
+
clear(): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
type AnyAchievementStorage = AchievementStorage | AsyncAchievementStorage;
|
|
62
|
+
declare function isAsyncStorage(storage: AnyAchievementStorage): storage is AsyncAchievementStorage;
|
|
54
63
|
interface AchievementContextValue {
|
|
55
64
|
updateMetrics: (metrics: AchievementMetrics | ((prev: AchievementMetrics) => AchievementMetrics)) => void;
|
|
56
65
|
unlockedAchievements: string[];
|
|
@@ -84,8 +93,10 @@ interface AchievementProviderProps$1 {
|
|
|
84
93
|
onAchievementUnlocked?: (achievement: AchievementDetails) => void;
|
|
85
94
|
}
|
|
86
95
|
declare enum StorageType {
|
|
87
|
-
Local = "local"
|
|
88
|
-
Memory = "memory"
|
|
96
|
+
Local = "local",// Synchronous localStorage
|
|
97
|
+
Memory = "memory",// Synchronous in-memory storage
|
|
98
|
+
IndexedDB = "indexeddb",// Asynchronous IndexedDB storage
|
|
99
|
+
RestAPI = "restapi"
|
|
89
100
|
}
|
|
90
101
|
|
|
91
102
|
declare class LocalStorage implements AchievementStorage {
|
|
@@ -115,6 +126,199 @@ declare class MemoryStorage implements AchievementStorage {
|
|
|
115
126
|
clear(): void;
|
|
116
127
|
}
|
|
117
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Base error class for all achievement-related errors
|
|
131
|
+
*/
|
|
132
|
+
declare class AchievementError extends Error {
|
|
133
|
+
code: string;
|
|
134
|
+
recoverable: boolean;
|
|
135
|
+
remedy?: string | undefined;
|
|
136
|
+
constructor(message: string, code: string, recoverable: boolean, remedy?: string | undefined);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Error thrown when browser storage quota is exceeded
|
|
140
|
+
*/
|
|
141
|
+
declare class StorageQuotaError extends AchievementError {
|
|
142
|
+
bytesNeeded: number;
|
|
143
|
+
constructor(bytesNeeded: number);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Error thrown when imported data fails validation
|
|
147
|
+
*/
|
|
148
|
+
declare class ImportValidationError extends AchievementError {
|
|
149
|
+
validationErrors: string[];
|
|
150
|
+
constructor(validationErrors: string[]);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Error thrown when storage operations fail
|
|
154
|
+
*/
|
|
155
|
+
declare class StorageError extends AchievementError {
|
|
156
|
+
originalError?: Error | undefined;
|
|
157
|
+
constructor(message: string, originalError?: Error | undefined);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Error thrown when configuration is invalid
|
|
161
|
+
*/
|
|
162
|
+
declare class ConfigurationError extends AchievementError {
|
|
163
|
+
constructor(message: string);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Error thrown when network sync operations fail
|
|
167
|
+
*/
|
|
168
|
+
declare class SyncError extends AchievementError {
|
|
169
|
+
readonly statusCode?: number;
|
|
170
|
+
readonly timeout?: number;
|
|
171
|
+
constructor(message: string, details?: {
|
|
172
|
+
statusCode?: number;
|
|
173
|
+
timeout?: number;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Type guard to check if an error is an AchievementError
|
|
178
|
+
*/
|
|
179
|
+
declare function isAchievementError(error: unknown): error is AchievementError;
|
|
180
|
+
/**
|
|
181
|
+
* Type guard to check if an error is recoverable
|
|
182
|
+
*/
|
|
183
|
+
declare function isRecoverableError(error: unknown): boolean;
|
|
184
|
+
|
|
185
|
+
declare class AsyncStorageAdapter implements AchievementStorage {
|
|
186
|
+
private asyncStorage;
|
|
187
|
+
private cache;
|
|
188
|
+
private pendingWrites;
|
|
189
|
+
private onError?;
|
|
190
|
+
constructor(asyncStorage: AsyncAchievementStorage, options?: {
|
|
191
|
+
onError?: (error: AchievementError) => void;
|
|
192
|
+
});
|
|
193
|
+
/**
|
|
194
|
+
* Initialize cache by loading from async storage
|
|
195
|
+
* This happens in the background during construction
|
|
196
|
+
*/
|
|
197
|
+
private initializeCache;
|
|
198
|
+
/**
|
|
199
|
+
* Wait for cache to be loaded (used internally)
|
|
200
|
+
* Returns immediately if already loaded, otherwise waits
|
|
201
|
+
*/
|
|
202
|
+
private ensureCacheLoaded;
|
|
203
|
+
/**
|
|
204
|
+
* SYNC READ: Returns cached metrics immediately
|
|
205
|
+
* Cache is loaded eagerly during construction
|
|
206
|
+
*/
|
|
207
|
+
getMetrics(): AchievementMetrics;
|
|
208
|
+
/**
|
|
209
|
+
* SYNC WRITE: Updates cache immediately, writes to storage in background
|
|
210
|
+
* Uses optimistic updates - assumes write will succeed
|
|
211
|
+
*/
|
|
212
|
+
setMetrics(metrics: AchievementMetrics): void;
|
|
213
|
+
/**
|
|
214
|
+
* SYNC READ: Returns cached unlocked achievements immediately
|
|
215
|
+
*/
|
|
216
|
+
getUnlockedAchievements(): string[];
|
|
217
|
+
/**
|
|
218
|
+
* SYNC WRITE: Updates cache immediately, writes to storage in background
|
|
219
|
+
*/
|
|
220
|
+
setUnlockedAchievements(achievements: string[]): void;
|
|
221
|
+
/**
|
|
222
|
+
* SYNC CLEAR: Clears cache immediately, clears storage in background
|
|
223
|
+
*/
|
|
224
|
+
clear(): void;
|
|
225
|
+
/**
|
|
226
|
+
* Wait for all pending writes to complete (useful for testing/cleanup)
|
|
227
|
+
* NOT part of AchievementStorage interface - utility method
|
|
228
|
+
*/
|
|
229
|
+
flush(): Promise<void>;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
declare class IndexedDBStorage implements AsyncAchievementStorage {
|
|
233
|
+
private dbName;
|
|
234
|
+
private storeName;
|
|
235
|
+
private db;
|
|
236
|
+
private initPromise;
|
|
237
|
+
constructor(dbName?: string);
|
|
238
|
+
/**
|
|
239
|
+
* Initialize IndexedDB database and object store
|
|
240
|
+
*/
|
|
241
|
+
private initDB;
|
|
242
|
+
/**
|
|
243
|
+
* Generic get operation from IndexedDB
|
|
244
|
+
*/
|
|
245
|
+
private get;
|
|
246
|
+
/**
|
|
247
|
+
* Generic set operation to IndexedDB
|
|
248
|
+
*/
|
|
249
|
+
private set;
|
|
250
|
+
/**
|
|
251
|
+
* Delete operation from IndexedDB
|
|
252
|
+
*/
|
|
253
|
+
private delete;
|
|
254
|
+
getMetrics(): Promise<AchievementMetrics>;
|
|
255
|
+
setMetrics(metrics: AchievementMetrics): Promise<void>;
|
|
256
|
+
getUnlockedAchievements(): Promise<string[]>;
|
|
257
|
+
setUnlockedAchievements(achievements: string[]): Promise<void>;
|
|
258
|
+
clear(): Promise<void>;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
interface RestApiStorageConfig {
|
|
262
|
+
baseUrl: string;
|
|
263
|
+
userId: string;
|
|
264
|
+
headers?: Record<string, string>;
|
|
265
|
+
timeout?: number;
|
|
266
|
+
}
|
|
267
|
+
declare class RestApiStorage implements AsyncAchievementStorage {
|
|
268
|
+
private config;
|
|
269
|
+
constructor(config: RestApiStorageConfig);
|
|
270
|
+
/**
|
|
271
|
+
* Generic fetch wrapper with timeout and error handling
|
|
272
|
+
*/
|
|
273
|
+
private fetchWithTimeout;
|
|
274
|
+
getMetrics(): Promise<AchievementMetrics>;
|
|
275
|
+
setMetrics(metrics: AchievementMetrics): Promise<void>;
|
|
276
|
+
getUnlockedAchievements(): Promise<string[]>;
|
|
277
|
+
setUnlockedAchievements(achievements: string[]): Promise<void>;
|
|
278
|
+
clear(): Promise<void>;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
interface QueuedOperation {
|
|
282
|
+
id: string;
|
|
283
|
+
type: 'setMetrics' | 'setUnlockedAchievements' | 'clear';
|
|
284
|
+
data?: any;
|
|
285
|
+
timestamp: number;
|
|
286
|
+
}
|
|
287
|
+
declare class OfflineQueueStorage implements AsyncAchievementStorage {
|
|
288
|
+
private innerStorage;
|
|
289
|
+
private queue;
|
|
290
|
+
private isOnline;
|
|
291
|
+
private isSyncing;
|
|
292
|
+
private queueStorageKey;
|
|
293
|
+
constructor(innerStorage: AsyncAchievementStorage);
|
|
294
|
+
private loadQueue;
|
|
295
|
+
private saveQueue;
|
|
296
|
+
private handleOnline;
|
|
297
|
+
private handleOffline;
|
|
298
|
+
private processQueue;
|
|
299
|
+
private queueOperation;
|
|
300
|
+
getMetrics(): Promise<AchievementMetrics>;
|
|
301
|
+
setMetrics(metrics: AchievementMetrics): Promise<void>;
|
|
302
|
+
getUnlockedAchievements(): Promise<string[]>;
|
|
303
|
+
setUnlockedAchievements(achievements: string[]): Promise<void>;
|
|
304
|
+
clear(): Promise<void>;
|
|
305
|
+
/**
|
|
306
|
+
* Manually trigger queue processing (useful for testing)
|
|
307
|
+
*/
|
|
308
|
+
sync(): Promise<void>;
|
|
309
|
+
/**
|
|
310
|
+
* Get current queue status (useful for debugging)
|
|
311
|
+
*/
|
|
312
|
+
getQueueStatus(): {
|
|
313
|
+
pending: number;
|
|
314
|
+
operations: QueuedOperation[];
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
* Cleanup listeners (call on unmount)
|
|
318
|
+
*/
|
|
319
|
+
destroy(): void;
|
|
320
|
+
}
|
|
321
|
+
|
|
118
322
|
interface BadgesButtonProps {
|
|
119
323
|
onClick: () => void;
|
|
120
324
|
position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
@@ -137,6 +341,56 @@ interface ConfettiWrapperProps {
|
|
|
137
341
|
}
|
|
138
342
|
declare const ConfettiWrapper: React$1.FC<ConfettiWrapperProps>;
|
|
139
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Options for importing achievement data
|
|
346
|
+
*/
|
|
347
|
+
interface ImportOptions {
|
|
348
|
+
/** Strategy for merging imported data with existing data */
|
|
349
|
+
mergeStrategy?: 'replace' | 'merge' | 'preserve';
|
|
350
|
+
/** Whether to validate the imported data */
|
|
351
|
+
validate?: boolean;
|
|
352
|
+
/** Optional config hash to validate against */
|
|
353
|
+
expectedConfigHash?: string;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Result of an import operation
|
|
357
|
+
*/
|
|
358
|
+
interface ImportResult {
|
|
359
|
+
success: boolean;
|
|
360
|
+
imported: {
|
|
361
|
+
metrics: number;
|
|
362
|
+
achievements: number;
|
|
363
|
+
};
|
|
364
|
+
errors?: string[];
|
|
365
|
+
warnings?: string[];
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Imports achievement data from a JSON string
|
|
369
|
+
*
|
|
370
|
+
* @param jsonString - JSON string containing exported achievement data
|
|
371
|
+
* @param currentMetrics - Current metrics state
|
|
372
|
+
* @param currentUnlocked - Current unlocked achievements
|
|
373
|
+
* @param options - Import options
|
|
374
|
+
* @returns Import result with success status and any errors
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```typescript
|
|
378
|
+
* const result = importAchievementData(
|
|
379
|
+
* jsonString,
|
|
380
|
+
* currentMetrics,
|
|
381
|
+
* currentUnlocked,
|
|
382
|
+
* { mergeStrategy: 'merge', validate: true }
|
|
383
|
+
* );
|
|
384
|
+
*
|
|
385
|
+
* if (result.success) {
|
|
386
|
+
* console.log(`Imported ${result.imported.achievements} achievements`);
|
|
387
|
+
* } else {
|
|
388
|
+
* console.error('Import failed:', result.errors);
|
|
389
|
+
* }
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
declare function importAchievementData(jsonString: string, currentMetrics: AchievementMetrics, currentUnlocked: string[], options?: ImportOptions): ImportResult;
|
|
393
|
+
|
|
140
394
|
interface AchievementContextType {
|
|
141
395
|
update: (metrics: Record<string, any>) => void;
|
|
142
396
|
achievements: {
|
|
@@ -148,13 +402,17 @@ interface AchievementContextType {
|
|
|
148
402
|
metrics: AchievementMetrics;
|
|
149
403
|
unlocked: string[];
|
|
150
404
|
};
|
|
405
|
+
exportData: () => string;
|
|
406
|
+
importData: (jsonString: string, options?: ImportOptions) => ImportResult;
|
|
151
407
|
}
|
|
152
408
|
declare const AchievementContext: React$1.Context<AchievementContextType | undefined>;
|
|
153
409
|
interface AchievementProviderProps {
|
|
154
410
|
achievements: AchievementConfigurationType;
|
|
155
|
-
storage?: AchievementStorage | StorageType;
|
|
411
|
+
storage?: AchievementStorage | AsyncAchievementStorage | StorageType;
|
|
156
412
|
children: React$1.ReactNode;
|
|
157
413
|
icons?: Record<string, string>;
|
|
414
|
+
onError?: (error: AchievementError) => void;
|
|
415
|
+
restApiConfig?: RestApiStorageConfig;
|
|
158
416
|
}
|
|
159
417
|
declare const AchievementProvider: React$1.FC<AchievementProviderProps>;
|
|
160
418
|
|
|
@@ -205,6 +463,18 @@ declare const useSimpleAchievements: () => {
|
|
|
205
463
|
metrics: AchievementMetrics;
|
|
206
464
|
unlocked: string[];
|
|
207
465
|
};
|
|
466
|
+
/**
|
|
467
|
+
* Export achievement data to JSON string
|
|
468
|
+
* @returns JSON string containing all achievement data
|
|
469
|
+
*/
|
|
470
|
+
exportData: () => string;
|
|
471
|
+
/**
|
|
472
|
+
* Import achievement data from JSON string
|
|
473
|
+
* @param jsonString - JSON string containing exported achievement data
|
|
474
|
+
* @param options - Import options (merge strategy, validation)
|
|
475
|
+
* @returns Import result with success status and any errors
|
|
476
|
+
*/
|
|
477
|
+
importData: (jsonString: string, options?: ImportOptions) => ImportResult;
|
|
208
478
|
};
|
|
209
479
|
|
|
210
480
|
declare const defaultStyles: Required<StylesProps>;
|
|
@@ -355,4 +625,38 @@ declare class AchievementBuilder {
|
|
|
355
625
|
static combine(achievements: (SimpleAchievementConfig | Achievement)[]): SimpleAchievementConfig;
|
|
356
626
|
}
|
|
357
627
|
|
|
358
|
-
|
|
628
|
+
/**
|
|
629
|
+
* Structure of exported achievement data
|
|
630
|
+
*/
|
|
631
|
+
interface ExportedData {
|
|
632
|
+
version: string;
|
|
633
|
+
timestamp: number;
|
|
634
|
+
metrics: AchievementMetrics;
|
|
635
|
+
unlockedAchievements: string[];
|
|
636
|
+
configHash?: string;
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Exports achievement data to a JSON string
|
|
640
|
+
*
|
|
641
|
+
* @param metrics - Current achievement metrics
|
|
642
|
+
* @param unlocked - Array of unlocked achievement IDs
|
|
643
|
+
* @param configHash - Optional hash of achievement configuration for validation
|
|
644
|
+
* @returns JSON string containing all achievement data
|
|
645
|
+
*
|
|
646
|
+
* @example
|
|
647
|
+
* ```typescript
|
|
648
|
+
* const json = exportAchievementData(metrics, ['score_100', 'level_5']);
|
|
649
|
+
* // Save json to file or send to server
|
|
650
|
+
* ```
|
|
651
|
+
*/
|
|
652
|
+
declare function exportAchievementData(metrics: AchievementMetrics, unlocked: string[], configHash?: string): string;
|
|
653
|
+
/**
|
|
654
|
+
* Creates a simple hash of the achievement configuration
|
|
655
|
+
* Used to validate that imported data matches the current configuration
|
|
656
|
+
*
|
|
657
|
+
* @param config - Achievement configuration object
|
|
658
|
+
* @returns Simple hash string
|
|
659
|
+
*/
|
|
660
|
+
declare function createConfigHash(config: any): string;
|
|
661
|
+
|
|
662
|
+
export { AchievementBuilder, AchievementCondition, AchievementConfiguration, AchievementConfigurationType, AchievementContext, AchievementContextValue, AchievementDetails, AchievementError, AchievementMetricArrayValue, AchievementMetricValue, AchievementMetrics, AchievementProvider, AchievementProviderProps$1 as AchievementProviderProps, AchievementState, AchievementStorage, AnyAchievementStorage, AsyncAchievementStorage, AsyncStorageAdapter, AwardDetails, BadgesButton, BadgesModal, ConfettiWrapper, ConfigurationError, CustomAchievementDetails, ExportedData, ImportOptions, ImportResult, ImportValidationError, IndexedDBStorage, InitialAchievementMetrics, LocalStorage, MemoryStorage, OfflineQueueStorage, RestApiStorage, RestApiStorageConfig, SimpleAchievementConfig, SimpleAchievementDetails, StorageError, StorageQuotaError, StorageType, StylesProps, SyncError, createConfigHash, defaultAchievementIcons, defaultStyles, exportAchievementData, importAchievementData, isAchievementError, isAsyncStorage, isRecoverableError, isSimpleConfig, normalizeAchievements, useAchievements, useSimpleAchievements };
|