achievements-engine 1.0.0 → 1.1.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/dist/index.cjs +271 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +143 -3
- package/dist/index.esm.js +270 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +271 -0
- package/dist/index.umd.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -226,6 +226,14 @@ interface ImportResult$1 {
|
|
|
226
226
|
mergedMetrics?: AchievementMetrics;
|
|
227
227
|
mergedUnlocked?: string[];
|
|
228
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Helper interface for cleaner achievement award definitions
|
|
231
|
+
*/
|
|
232
|
+
interface AwardDetails {
|
|
233
|
+
title?: string;
|
|
234
|
+
description?: string;
|
|
235
|
+
icon?: string;
|
|
236
|
+
}
|
|
229
237
|
/**
|
|
230
238
|
* Public API surface of the AchievementEngine
|
|
231
239
|
* This type represents the stable, supported API for external consumers
|
|
@@ -272,7 +280,7 @@ declare class AchievementEngine extends EventEmitter {
|
|
|
272
280
|
* Update metrics and evaluate achievements
|
|
273
281
|
* @param newMetrics - Metrics to update
|
|
274
282
|
*/
|
|
275
|
-
update
|
|
283
|
+
update<T extends Record<string, any>>(newMetrics: Partial<T>): void;
|
|
276
284
|
/**
|
|
277
285
|
* Evaluate all achievements and unlock any newly met conditions
|
|
278
286
|
* This is the core evaluation logic extracted from AchievementProvider
|
|
@@ -285,7 +293,7 @@ declare class AchievementEngine extends EventEmitter {
|
|
|
285
293
|
/**
|
|
286
294
|
* Get current metrics (readonly to prevent external modification)
|
|
287
295
|
*/
|
|
288
|
-
getMetrics(): Readonly<
|
|
296
|
+
getMetrics<T extends Record<string, any>>(): Readonly<Partial<T>>;
|
|
289
297
|
/**
|
|
290
298
|
* Get unlocked achievement IDs (readonly)
|
|
291
299
|
*/
|
|
@@ -556,8 +564,19 @@ declare class OfflineQueueStorage implements AsyncAchievementStorage {
|
|
|
556
564
|
destroy(): void;
|
|
557
565
|
}
|
|
558
566
|
|
|
567
|
+
declare function isSimpleConfig(config: AchievementConfigurationType): config is SimpleAchievementConfig;
|
|
559
568
|
declare function normalizeAchievements(config: AchievementConfigurationType): AchievementConfiguration;
|
|
560
569
|
|
|
570
|
+
/**
|
|
571
|
+
* Structure of exported achievement data
|
|
572
|
+
*/
|
|
573
|
+
interface ExportedData {
|
|
574
|
+
version: string;
|
|
575
|
+
timestamp: number;
|
|
576
|
+
metrics: AchievementMetrics;
|
|
577
|
+
unlockedAchievements: string[];
|
|
578
|
+
configHash?: string;
|
|
579
|
+
}
|
|
561
580
|
/**
|
|
562
581
|
* Exports achievement data to a JSON string
|
|
563
582
|
*
|
|
@@ -632,4 +651,125 @@ interface ImportResult {
|
|
|
632
651
|
*/
|
|
633
652
|
declare function importAchievementData(jsonString: string, currentMetrics: AchievementMetrics, currentUnlocked: string[], options?: ImportOptions): ImportResult;
|
|
634
653
|
|
|
635
|
-
|
|
654
|
+
/**
|
|
655
|
+
* Base class for chainable achievement configuration (Tier 2)
|
|
656
|
+
*/
|
|
657
|
+
declare abstract class Achievement {
|
|
658
|
+
protected metric: string;
|
|
659
|
+
protected award: AwardDetails;
|
|
660
|
+
constructor(metric: string, defaultAward: AwardDetails);
|
|
661
|
+
/**
|
|
662
|
+
* Customize the award details for this achievement
|
|
663
|
+
* @param award - Custom award details
|
|
664
|
+
* @returns This achievement for chaining
|
|
665
|
+
*/
|
|
666
|
+
withAward(award: AwardDetails): Achievement;
|
|
667
|
+
/**
|
|
668
|
+
* Convert this achievement to a SimpleAchievementConfig
|
|
669
|
+
*/
|
|
670
|
+
abstract toConfig(): SimpleAchievementConfig;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Threshold-based achievement (score, level, etc.)
|
|
674
|
+
*/
|
|
675
|
+
declare class ThresholdAchievement extends Achievement {
|
|
676
|
+
private threshold;
|
|
677
|
+
constructor(metric: string, threshold: number, defaultAward: AwardDetails);
|
|
678
|
+
toConfig(): SimpleAchievementConfig;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Boolean achievement (tutorial completion, first login, etc.)
|
|
682
|
+
*/
|
|
683
|
+
declare class BooleanAchievement extends Achievement {
|
|
684
|
+
toConfig(): SimpleAchievementConfig;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Value-based achievement (character class, difficulty, etc.)
|
|
688
|
+
*/
|
|
689
|
+
declare class ValueAchievement extends Achievement {
|
|
690
|
+
private value;
|
|
691
|
+
constructor(metric: string, value: string, defaultAward: AwardDetails);
|
|
692
|
+
toConfig(): SimpleAchievementConfig;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Complex achievement builder for power users (Tier 3)
|
|
696
|
+
*/
|
|
697
|
+
declare class ComplexAchievementBuilder {
|
|
698
|
+
private metric;
|
|
699
|
+
private condition;
|
|
700
|
+
private award;
|
|
701
|
+
/**
|
|
702
|
+
* Set the metric this achievement tracks
|
|
703
|
+
*/
|
|
704
|
+
withMetric(metric: string): ComplexAchievementBuilder;
|
|
705
|
+
/**
|
|
706
|
+
* Set the condition function that determines if achievement is unlocked
|
|
707
|
+
*/
|
|
708
|
+
withCondition(fn: (metrics: Record<string, any>) => boolean): ComplexAchievementBuilder;
|
|
709
|
+
/**
|
|
710
|
+
* Set the award details for this achievement
|
|
711
|
+
*/
|
|
712
|
+
withAward(award: AwardDetails): ComplexAchievementBuilder;
|
|
713
|
+
/**
|
|
714
|
+
* Build the final achievement configuration
|
|
715
|
+
*/
|
|
716
|
+
build(): SimpleAchievementConfig;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Main AchievementBuilder with three-tier API
|
|
720
|
+
* Tier 1: Simple static methods with smart defaults
|
|
721
|
+
* Tier 2: Chainable customization
|
|
722
|
+
* Tier 3: Full builder for complex logic
|
|
723
|
+
*/
|
|
724
|
+
declare class AchievementBuilder {
|
|
725
|
+
/**
|
|
726
|
+
* Create a single score achievement with smart defaults
|
|
727
|
+
* @param threshold - Score threshold to achieve
|
|
728
|
+
* @returns Chainable ThresholdAchievement
|
|
729
|
+
*/
|
|
730
|
+
static createScoreAchievement(threshold: number): ThresholdAchievement;
|
|
731
|
+
/**
|
|
732
|
+
* Create multiple score achievements
|
|
733
|
+
* @param thresholds - Array of thresholds or [threshold, award] tuples
|
|
734
|
+
* @returns Complete SimpleAchievementConfig
|
|
735
|
+
*/
|
|
736
|
+
static createScoreAchievements(thresholds: (number | [number, AwardDetails])[]): SimpleAchievementConfig;
|
|
737
|
+
/**
|
|
738
|
+
* Create a single level achievement with smart defaults
|
|
739
|
+
* @param level - Level threshold to achieve
|
|
740
|
+
* @returns Chainable ThresholdAchievement
|
|
741
|
+
*/
|
|
742
|
+
static createLevelAchievement(level: number): ThresholdAchievement;
|
|
743
|
+
/**
|
|
744
|
+
* Create multiple level achievements
|
|
745
|
+
* @param levels - Array of levels or [level, award] tuples
|
|
746
|
+
* @returns Complete SimpleAchievementConfig
|
|
747
|
+
*/
|
|
748
|
+
static createLevelAchievements(levels: (number | [number, AwardDetails])[]): SimpleAchievementConfig;
|
|
749
|
+
/**
|
|
750
|
+
* Create a boolean achievement with smart defaults
|
|
751
|
+
* @param metric - The metric name (e.g., 'completedTutorial')
|
|
752
|
+
* @returns Chainable BooleanAchievement
|
|
753
|
+
*/
|
|
754
|
+
static createBooleanAchievement(metric: string): BooleanAchievement;
|
|
755
|
+
/**
|
|
756
|
+
* Create a value-based achievement with smart defaults
|
|
757
|
+
* @param metric - The metric name (e.g., 'characterClass')
|
|
758
|
+
* @param value - The value to match (e.g., 'wizard')
|
|
759
|
+
* @returns Chainable ValueAchievement
|
|
760
|
+
*/
|
|
761
|
+
static createValueAchievement(metric: string, value: string): ValueAchievement;
|
|
762
|
+
/**
|
|
763
|
+
* Create a complex achievement builder for power users
|
|
764
|
+
* @returns ComplexAchievementBuilder for full control
|
|
765
|
+
*/
|
|
766
|
+
static create(): ComplexAchievementBuilder;
|
|
767
|
+
/**
|
|
768
|
+
* Combine multiple achievement configurations
|
|
769
|
+
* @param achievements - Array of SimpleAchievementConfig objects or Achievement instances
|
|
770
|
+
* @returns Combined SimpleAchievementConfig
|
|
771
|
+
*/
|
|
772
|
+
static combine(achievements: (SimpleAchievementConfig | Achievement)[]): SimpleAchievementConfig;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
export { AchievementBuilder, AchievementCondition, AchievementConfiguration, AchievementConfigurationType, AchievementDetails, AchievementEngine, AchievementEngineApi, AchievementError, AchievementMetricArrayValue, AchievementMetricValue, AchievementMetrics, AchievementState, AchievementStorage, AchievementUnlockedEvent, AchievementWithStatus, AnyAchievementStorage, AsyncAchievementStorage, AsyncStorageAdapter, AwardDetails, ConfigurationError, CustomAchievementDetails, EngineConfig, EngineEvent, ErrorEvent, EventEmitter, EventHandler, EventMapping, ExportedData, ImportOptions$1 as ImportOptions, ImportResult$1 as ImportResult, ImportValidationError, IndexedDBStorage, InitialAchievementMetrics, LocalStorage, MemoryStorage, MetricUpdatedEvent, MetricUpdater, OfflineQueueStorage, RestApiStorage, RestApiStorageConfig$1 as RestApiStorageConfig, SimpleAchievementConfig, SimpleAchievementDetails, StateChangedEvent, StorageError, StorageQuotaError, StorageType, SyncError, UnsubscribeFn, createConfigHash, exportAchievementData, importAchievementData, isAchievementError, isAsyncStorage, isRecoverableError, isSimpleConfig, normalizeAchievements };
|
package/dist/index.esm.js
CHANGED
|
@@ -1673,5 +1673,274 @@ class OfflineQueueStorage {
|
|
|
1673
1673
|
}
|
|
1674
1674
|
}
|
|
1675
1675
|
|
|
1676
|
-
|
|
1676
|
+
/**
|
|
1677
|
+
* Base class for chainable achievement configuration (Tier 2)
|
|
1678
|
+
*/
|
|
1679
|
+
class Achievement {
|
|
1680
|
+
constructor(metric, defaultAward) {
|
|
1681
|
+
this.metric = metric;
|
|
1682
|
+
this.award = defaultAward;
|
|
1683
|
+
}
|
|
1684
|
+
/**
|
|
1685
|
+
* Customize the award details for this achievement
|
|
1686
|
+
* @param award - Custom award details
|
|
1687
|
+
* @returns This achievement for chaining
|
|
1688
|
+
*/
|
|
1689
|
+
withAward(award) {
|
|
1690
|
+
this.award = Object.assign(Object.assign({}, this.award), award);
|
|
1691
|
+
return this;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
/**
|
|
1695
|
+
* Threshold-based achievement (score, level, etc.)
|
|
1696
|
+
*/
|
|
1697
|
+
class ThresholdAchievement extends Achievement {
|
|
1698
|
+
constructor(metric, threshold, defaultAward) {
|
|
1699
|
+
super(metric, defaultAward);
|
|
1700
|
+
this.threshold = threshold;
|
|
1701
|
+
}
|
|
1702
|
+
toConfig() {
|
|
1703
|
+
return {
|
|
1704
|
+
[this.metric]: {
|
|
1705
|
+
[this.threshold]: {
|
|
1706
|
+
title: this.award.title,
|
|
1707
|
+
description: this.award.description,
|
|
1708
|
+
icon: this.award.icon
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Boolean achievement (tutorial completion, first login, etc.)
|
|
1716
|
+
*/
|
|
1717
|
+
class BooleanAchievement extends Achievement {
|
|
1718
|
+
toConfig() {
|
|
1719
|
+
return {
|
|
1720
|
+
[this.metric]: {
|
|
1721
|
+
true: {
|
|
1722
|
+
title: this.award.title,
|
|
1723
|
+
description: this.award.description,
|
|
1724
|
+
icon: this.award.icon
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Value-based achievement (character class, difficulty, etc.)
|
|
1732
|
+
*/
|
|
1733
|
+
class ValueAchievement extends Achievement {
|
|
1734
|
+
constructor(metric, value, defaultAward) {
|
|
1735
|
+
super(metric, defaultAward);
|
|
1736
|
+
this.value = value;
|
|
1737
|
+
}
|
|
1738
|
+
toConfig() {
|
|
1739
|
+
return {
|
|
1740
|
+
[this.metric]: {
|
|
1741
|
+
[this.value]: {
|
|
1742
|
+
title: this.award.title,
|
|
1743
|
+
description: this.award.description,
|
|
1744
|
+
icon: this.award.icon
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
/**
|
|
1751
|
+
* Complex achievement builder for power users (Tier 3)
|
|
1752
|
+
*/
|
|
1753
|
+
class ComplexAchievementBuilder {
|
|
1754
|
+
constructor() {
|
|
1755
|
+
this.metric = '';
|
|
1756
|
+
this.condition = null;
|
|
1757
|
+
this.award = {};
|
|
1758
|
+
}
|
|
1759
|
+
/**
|
|
1760
|
+
* Set the metric this achievement tracks
|
|
1761
|
+
*/
|
|
1762
|
+
withMetric(metric) {
|
|
1763
|
+
this.metric = metric;
|
|
1764
|
+
return this;
|
|
1765
|
+
}
|
|
1766
|
+
/**
|
|
1767
|
+
* Set the condition function that determines if achievement is unlocked
|
|
1768
|
+
*/
|
|
1769
|
+
withCondition(fn) {
|
|
1770
|
+
this.condition = fn;
|
|
1771
|
+
return this;
|
|
1772
|
+
}
|
|
1773
|
+
/**
|
|
1774
|
+
* Set the award details for this achievement
|
|
1775
|
+
*/
|
|
1776
|
+
withAward(award) {
|
|
1777
|
+
this.award = Object.assign(Object.assign({}, this.award), award);
|
|
1778
|
+
return this;
|
|
1779
|
+
}
|
|
1780
|
+
/**
|
|
1781
|
+
* Build the final achievement configuration
|
|
1782
|
+
*/
|
|
1783
|
+
build() {
|
|
1784
|
+
if (!this.metric || !this.condition) {
|
|
1785
|
+
throw new Error('Complex achievement requires metric and condition');
|
|
1786
|
+
}
|
|
1787
|
+
return {
|
|
1788
|
+
[this.metric]: {
|
|
1789
|
+
custom: {
|
|
1790
|
+
title: this.award.title || this.metric,
|
|
1791
|
+
description: this.award.description || `Achieve ${this.award.title || this.metric}`,
|
|
1792
|
+
icon: this.award.icon || '💎',
|
|
1793
|
+
condition: this.condition
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
/**
|
|
1800
|
+
* Main AchievementBuilder with three-tier API
|
|
1801
|
+
* Tier 1: Simple static methods with smart defaults
|
|
1802
|
+
* Tier 2: Chainable customization
|
|
1803
|
+
* Tier 3: Full builder for complex logic
|
|
1804
|
+
*/
|
|
1805
|
+
class AchievementBuilder {
|
|
1806
|
+
// TIER 1: Simple Static Methods (90% of use cases)
|
|
1807
|
+
/**
|
|
1808
|
+
* Create a single score achievement with smart defaults
|
|
1809
|
+
* @param threshold - Score threshold to achieve
|
|
1810
|
+
* @returns Chainable ThresholdAchievement
|
|
1811
|
+
*/
|
|
1812
|
+
static createScoreAchievement(threshold) {
|
|
1813
|
+
return new ThresholdAchievement('score', threshold, {
|
|
1814
|
+
title: `Score ${threshold}!`,
|
|
1815
|
+
description: `Score ${threshold} points`,
|
|
1816
|
+
icon: '🏆'
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
/**
|
|
1820
|
+
* Create multiple score achievements
|
|
1821
|
+
* @param thresholds - Array of thresholds or [threshold, award] tuples
|
|
1822
|
+
* @returns Complete SimpleAchievementConfig
|
|
1823
|
+
*/
|
|
1824
|
+
static createScoreAchievements(thresholds) {
|
|
1825
|
+
const config = { score: {} };
|
|
1826
|
+
thresholds.forEach(item => {
|
|
1827
|
+
if (typeof item === 'number') {
|
|
1828
|
+
// Use default award
|
|
1829
|
+
config.score[item] = {
|
|
1830
|
+
title: `Score ${item}!`,
|
|
1831
|
+
description: `Score ${item} points`,
|
|
1832
|
+
icon: '🏆'
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
else {
|
|
1836
|
+
// Custom award
|
|
1837
|
+
const [threshold, award] = item;
|
|
1838
|
+
config.score[threshold] = {
|
|
1839
|
+
title: award.title || `Score ${threshold}!`,
|
|
1840
|
+
description: award.description || `Score ${threshold} points`,
|
|
1841
|
+
icon: award.icon || '🏆'
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
});
|
|
1845
|
+
return config;
|
|
1846
|
+
}
|
|
1847
|
+
/**
|
|
1848
|
+
* Create a single level achievement with smart defaults
|
|
1849
|
+
* @param level - Level threshold to achieve
|
|
1850
|
+
* @returns Chainable ThresholdAchievement
|
|
1851
|
+
*/
|
|
1852
|
+
static createLevelAchievement(level) {
|
|
1853
|
+
return new ThresholdAchievement('level', level, {
|
|
1854
|
+
title: `Level ${level}!`,
|
|
1855
|
+
description: `Reach level ${level}`,
|
|
1856
|
+
icon: '📈'
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1859
|
+
/**
|
|
1860
|
+
* Create multiple level achievements
|
|
1861
|
+
* @param levels - Array of levels or [level, award] tuples
|
|
1862
|
+
* @returns Complete SimpleAchievementConfig
|
|
1863
|
+
*/
|
|
1864
|
+
static createLevelAchievements(levels) {
|
|
1865
|
+
const config = { level: {} };
|
|
1866
|
+
levels.forEach(item => {
|
|
1867
|
+
if (typeof item === 'number') {
|
|
1868
|
+
// Use default award
|
|
1869
|
+
config.level[item] = {
|
|
1870
|
+
title: `Level ${item}!`,
|
|
1871
|
+
description: `Reach level ${item}`,
|
|
1872
|
+
icon: '📈'
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
else {
|
|
1876
|
+
// Custom award
|
|
1877
|
+
const [level, award] = item;
|
|
1878
|
+
config.level[level] = {
|
|
1879
|
+
title: award.title || `Level ${level}!`,
|
|
1880
|
+
description: award.description || `Reach level ${level}`,
|
|
1881
|
+
icon: award.icon || '📈'
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
});
|
|
1885
|
+
return config;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Create a boolean achievement with smart defaults
|
|
1889
|
+
* @param metric - The metric name (e.g., 'completedTutorial')
|
|
1890
|
+
* @returns Chainable BooleanAchievement
|
|
1891
|
+
*/
|
|
1892
|
+
static createBooleanAchievement(metric) {
|
|
1893
|
+
// Convert camelCase to Title Case
|
|
1894
|
+
const formattedMetric = metric.replace(/([A-Z])/g, ' $1').toLowerCase();
|
|
1895
|
+
const titleCase = formattedMetric.charAt(0).toUpperCase() + formattedMetric.slice(1);
|
|
1896
|
+
return new BooleanAchievement(metric, {
|
|
1897
|
+
title: `${titleCase}!`,
|
|
1898
|
+
description: `Complete ${formattedMetric}`,
|
|
1899
|
+
icon: '✅'
|
|
1900
|
+
});
|
|
1901
|
+
}
|
|
1902
|
+
/**
|
|
1903
|
+
* Create a value-based achievement with smart defaults
|
|
1904
|
+
* @param metric - The metric name (e.g., 'characterClass')
|
|
1905
|
+
* @param value - The value to match (e.g., 'wizard')
|
|
1906
|
+
* @returns Chainable ValueAchievement
|
|
1907
|
+
*/
|
|
1908
|
+
static createValueAchievement(metric, value) {
|
|
1909
|
+
const formattedValue = value.charAt(0).toUpperCase() + value.slice(1);
|
|
1910
|
+
return new ValueAchievement(metric, value, {
|
|
1911
|
+
title: `${formattedValue}!`,
|
|
1912
|
+
description: `Choose ${formattedValue.toLowerCase()} for ${metric}`,
|
|
1913
|
+
icon: '🎯'
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
// TIER 3: Full Builder for Complex Logic
|
|
1917
|
+
/**
|
|
1918
|
+
* Create a complex achievement builder for power users
|
|
1919
|
+
* @returns ComplexAchievementBuilder for full control
|
|
1920
|
+
*/
|
|
1921
|
+
static create() {
|
|
1922
|
+
return new ComplexAchievementBuilder();
|
|
1923
|
+
}
|
|
1924
|
+
// UTILITY METHODS
|
|
1925
|
+
/**
|
|
1926
|
+
* Combine multiple achievement configurations
|
|
1927
|
+
* @param achievements - Array of SimpleAchievementConfig objects or Achievement instances
|
|
1928
|
+
* @returns Combined SimpleAchievementConfig
|
|
1929
|
+
*/
|
|
1930
|
+
static combine(achievements) {
|
|
1931
|
+
const combined = {};
|
|
1932
|
+
achievements.forEach(achievement => {
|
|
1933
|
+
const config = achievement instanceof Achievement ? achievement.toConfig() : achievement;
|
|
1934
|
+
Object.keys(config).forEach(key => {
|
|
1935
|
+
if (!combined[key]) {
|
|
1936
|
+
combined[key] = {};
|
|
1937
|
+
}
|
|
1938
|
+
Object.assign(combined[key], config[key]);
|
|
1939
|
+
});
|
|
1940
|
+
});
|
|
1941
|
+
return combined;
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
export { AchievementBuilder, AchievementEngine, AchievementError, AsyncStorageAdapter, ConfigurationError, EventEmitter, ImportValidationError, IndexedDBStorage, LocalStorage, MemoryStorage, OfflineQueueStorage, RestApiStorage, StorageError, StorageQuotaError, StorageType, SyncError, createConfigHash, exportAchievementData, importAchievementData, isAchievementError, isAsyncStorage, isRecoverableError, isSimpleConfig, normalizeAchievements };
|
|
1677
1946
|
//# sourceMappingURL=index.esm.js.map
|