@abdokouta/react-support 1.1.0 → 1.2.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/CHANGELOG.md +26 -0
- package/README.md +98 -54
- package/dist/index.d.cts +255 -676
- package/dist/index.d.ts +255 -676
- package/dist/index.js +217 -628
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +219 -628
- package/dist/index.mjs.map +1 -1
- package/package.json +22 -18
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
1
5
|
// src/str/str.ts
|
|
2
6
|
var Str = class _Str {
|
|
3
7
|
/**
|
|
@@ -20,7 +24,23 @@ var Str = class _Str {
|
|
|
20
24
|
* Convert a string to title case following APA guidelines
|
|
21
25
|
*/
|
|
22
26
|
static apa(value) {
|
|
23
|
-
const minorWords = [
|
|
27
|
+
const minorWords = [
|
|
28
|
+
"a",
|
|
29
|
+
"an",
|
|
30
|
+
"and",
|
|
31
|
+
"as",
|
|
32
|
+
"at",
|
|
33
|
+
"but",
|
|
34
|
+
"by",
|
|
35
|
+
"for",
|
|
36
|
+
"in",
|
|
37
|
+
"of",
|
|
38
|
+
"on",
|
|
39
|
+
"or",
|
|
40
|
+
"the",
|
|
41
|
+
"to",
|
|
42
|
+
"up"
|
|
43
|
+
];
|
|
24
44
|
const words = value.split(" ");
|
|
25
45
|
return words.map((word, index) => {
|
|
26
46
|
if (index === 0 || !minorWords.includes(word.toLowerCase())) {
|
|
@@ -628,6 +648,7 @@ var Str = class _Str {
|
|
|
628
648
|
import collectJs from "collect.js";
|
|
629
649
|
var Collection = class _Collection {
|
|
630
650
|
constructor(items = []) {
|
|
651
|
+
__publicField(this, "collection");
|
|
631
652
|
this.collection = collectJs(items);
|
|
632
653
|
}
|
|
633
654
|
/**
|
|
@@ -780,7 +801,10 @@ var Collection = class _Collection {
|
|
|
780
801
|
* Join all items from the collection using a string
|
|
781
802
|
*/
|
|
782
803
|
join(glue, finalGlue) {
|
|
783
|
-
|
|
804
|
+
if (finalGlue) {
|
|
805
|
+
return this.collection.join(glue, finalGlue);
|
|
806
|
+
}
|
|
807
|
+
return this.collection.join(glue);
|
|
784
808
|
}
|
|
785
809
|
/**
|
|
786
810
|
* Key the collection by the given key
|
|
@@ -1039,6 +1063,7 @@ function collect(items = []) {
|
|
|
1039
1063
|
// src/collections/map.collection.ts
|
|
1040
1064
|
var MapCollection = class _MapCollection {
|
|
1041
1065
|
constructor(entries) {
|
|
1066
|
+
__publicField(this, "internalMap");
|
|
1042
1067
|
if (entries && typeof entries === "object" && !(Symbol.iterator in entries)) {
|
|
1043
1068
|
this.internalMap = new Map(Object.entries(entries));
|
|
1044
1069
|
} else {
|
|
@@ -1338,6 +1363,7 @@ function collectMap(entries) {
|
|
|
1338
1363
|
// src/collections/set.collection.ts
|
|
1339
1364
|
var SetCollection = class _SetCollection {
|
|
1340
1365
|
constructor(items) {
|
|
1366
|
+
__publicField(this, "set");
|
|
1341
1367
|
this.set = new Set(items);
|
|
1342
1368
|
}
|
|
1343
1369
|
/**
|
|
@@ -1655,731 +1681,296 @@ function collectSet(items) {
|
|
|
1655
1681
|
}
|
|
1656
1682
|
|
|
1657
1683
|
// src/registry/base-registry.ts
|
|
1658
|
-
var RegistryCollection = class {
|
|
1659
|
-
constructor() {
|
|
1660
|
-
this._storage = new MapCollection();
|
|
1661
|
-
}
|
|
1662
|
-
add(key, value) {
|
|
1663
|
-
this._storage.set(key, value);
|
|
1664
|
-
}
|
|
1665
|
-
get(key) {
|
|
1666
|
-
return this._storage.get(key);
|
|
1667
|
-
}
|
|
1668
|
-
getAll() {
|
|
1669
|
-
return this._storage.values();
|
|
1670
|
-
}
|
|
1671
|
-
getKeys() {
|
|
1672
|
-
return this._storage.keys();
|
|
1673
|
-
}
|
|
1674
|
-
getAsRecord() {
|
|
1675
|
-
return this._storage.toObject();
|
|
1676
|
-
}
|
|
1677
|
-
has(key) {
|
|
1678
|
-
return this._storage.has(key);
|
|
1679
|
-
}
|
|
1680
|
-
remove(key) {
|
|
1681
|
-
return this._storage.delete(key);
|
|
1682
|
-
}
|
|
1683
|
-
clear() {
|
|
1684
|
-
this._storage.clear();
|
|
1685
|
-
}
|
|
1686
|
-
size() {
|
|
1687
|
-
return this._storage.size();
|
|
1688
|
-
}
|
|
1689
|
-
isEmpty() {
|
|
1690
|
-
return this._storage.isEmpty();
|
|
1691
|
-
}
|
|
1692
|
-
forEach(callback) {
|
|
1693
|
-
this._storage.each((value, key) => {
|
|
1694
|
-
callback(value, key);
|
|
1695
|
-
});
|
|
1696
|
-
}
|
|
1697
|
-
map(callback) {
|
|
1698
|
-
const result = [];
|
|
1699
|
-
this._storage.each((value, key) => {
|
|
1700
|
-
result.push(callback(value, key));
|
|
1701
|
-
});
|
|
1702
|
-
return result;
|
|
1703
|
-
}
|
|
1704
|
-
filter(predicate) {
|
|
1705
|
-
const result = [];
|
|
1706
|
-
this._storage.each((value, key) => {
|
|
1707
|
-
if (predicate(value, key)) {
|
|
1708
|
-
result.push(value);
|
|
1709
|
-
}
|
|
1710
|
-
});
|
|
1711
|
-
return result;
|
|
1712
|
-
}
|
|
1713
|
-
find(predicate) {
|
|
1714
|
-
return this._storage.first(predicate);
|
|
1715
|
-
}
|
|
1716
|
-
};
|
|
1717
1684
|
var BaseRegistry = class {
|
|
1718
1685
|
/**
|
|
1719
|
-
*
|
|
1720
|
-
*
|
|
1721
|
-
*
|
|
1722
|
-
* item and validation hooks. By default, uses MapCollection for storage.
|
|
1723
|
-
*
|
|
1724
|
-
* @param options - Registry configuration options
|
|
1725
|
-
*
|
|
1726
|
-
* @example
|
|
1727
|
-
* ```typescript
|
|
1728
|
-
* // Simple registry without options
|
|
1729
|
-
* const registry = new BaseRegistry<Theme>();
|
|
1730
|
-
* ```
|
|
1731
|
-
*
|
|
1732
|
-
* @example
|
|
1733
|
-
* ```typescript
|
|
1734
|
-
* // Registry with default item
|
|
1735
|
-
* const registry = new BaseRegistry<Theme>({
|
|
1736
|
-
* defaultItem: defaultTheme
|
|
1737
|
-
* });
|
|
1738
|
-
* ```
|
|
1739
|
-
*
|
|
1740
|
-
* @example
|
|
1741
|
-
* ```typescript
|
|
1742
|
-
* // Registry with validation
|
|
1743
|
-
* const registry = new BaseRegistry<Theme>({
|
|
1744
|
-
* validateBeforeAdd: (key, theme) => {
|
|
1745
|
-
* if (!theme.name) {
|
|
1746
|
-
* return { valid: false, error: 'Theme must have a name' };
|
|
1747
|
-
* }
|
|
1748
|
-
* return { valid: true };
|
|
1749
|
-
* },
|
|
1750
|
-
* afterAdd: (key, theme) => {
|
|
1751
|
-
* console.log(`Registered theme: ${theme.name}`);
|
|
1752
|
-
* }
|
|
1753
|
-
* });
|
|
1754
|
-
* ```
|
|
1686
|
+
* Create a new registry.
|
|
1687
|
+
*
|
|
1688
|
+
* @param options - Optional default item, validation, and lifecycle hooks
|
|
1755
1689
|
*/
|
|
1756
1690
|
constructor(options = {}) {
|
|
1757
|
-
|
|
1691
|
+
/**
|
|
1692
|
+
* Internal map-based storage.
|
|
1693
|
+
*/
|
|
1694
|
+
__publicField(this, "storage", new MapCollection());
|
|
1695
|
+
/**
|
|
1696
|
+
* Fallback value returned by {@link get} when a key is missing.
|
|
1697
|
+
*/
|
|
1698
|
+
__publicField(this, "defaultItem");
|
|
1699
|
+
/**
|
|
1700
|
+
* Optional validation executed before every {@link register} call.
|
|
1701
|
+
*/
|
|
1702
|
+
__publicField(this, "validateBeforeAdd");
|
|
1703
|
+
/**
|
|
1704
|
+
* Optional callback executed after a successful {@link register}.
|
|
1705
|
+
*/
|
|
1706
|
+
__publicField(this, "afterAdd");
|
|
1758
1707
|
this.defaultItem = options.defaultItem;
|
|
1759
1708
|
this.validateBeforeAdd = options.validateBeforeAdd;
|
|
1760
1709
|
this.afterAdd = options.afterAdd;
|
|
1761
1710
|
}
|
|
1711
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1712
|
+
// Core
|
|
1713
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1762
1714
|
/**
|
|
1763
|
-
* Register
|
|
1764
|
-
*
|
|
1765
|
-
*
|
|
1766
|
-
*
|
|
1767
|
-
*
|
|
1768
|
-
*
|
|
1769
|
-
*
|
|
1770
|
-
* not added.
|
|
1771
|
-
*
|
|
1772
|
-
* If an afterAdd hook is configured, it will be called after the item
|
|
1773
|
-
* is successfully added.
|
|
1774
|
-
*
|
|
1775
|
-
* Time Complexity: O(1) + validation time
|
|
1776
|
-
*
|
|
1777
|
-
* @param key - Unique identifier for the item
|
|
1778
|
-
* @param item - Item to register
|
|
1715
|
+
* Register (add or replace) an item.
|
|
1716
|
+
*
|
|
1717
|
+
* Runs the `validateBeforeAdd` hook first; throws on failure.
|
|
1718
|
+
* Fires the `afterAdd` hook on success.
|
|
1719
|
+
*
|
|
1720
|
+
* @param key - Unique identifier
|
|
1721
|
+
* @param item - Value to store
|
|
1779
1722
|
* @throws Error if validation fails
|
|
1780
|
-
*
|
|
1781
|
-
* @example
|
|
1782
|
-
* ```typescript
|
|
1783
|
-
* const registry = new BaseRegistry<Theme>();
|
|
1784
|
-
*
|
|
1785
|
-
* // Register a theme
|
|
1786
|
-
* registry.register('blue', {
|
|
1787
|
-
* name: 'Blue',
|
|
1788
|
-
* colors: { accent: '#0000FF' }
|
|
1789
|
-
* });
|
|
1790
|
-
*
|
|
1791
|
-
* // Update existing theme
|
|
1792
|
-
* registry.register('blue', {
|
|
1793
|
-
* name: 'Blue',
|
|
1794
|
-
* colors: { accent: '#0066FF' }
|
|
1795
|
-
* });
|
|
1796
|
-
* ```
|
|
1797
1723
|
*/
|
|
1798
1724
|
register(key, item) {
|
|
1799
1725
|
if (this.validateBeforeAdd) {
|
|
1800
1726
|
const result = this.validateBeforeAdd(key, item);
|
|
1801
1727
|
if (!result.valid) {
|
|
1802
|
-
throw new Error(
|
|
1803
|
-
`Validation failed for key "${key}": ${result.error || "Unknown error"}`
|
|
1804
|
-
);
|
|
1728
|
+
throw new Error(`Validation failed for key "${key}": ${result.error || "Unknown error"}`);
|
|
1805
1729
|
}
|
|
1806
1730
|
}
|
|
1807
|
-
this.
|
|
1731
|
+
this.storage.set(key, item);
|
|
1808
1732
|
if (this.afterAdd) {
|
|
1809
1733
|
this.afterAdd(key, item);
|
|
1810
1734
|
}
|
|
1811
1735
|
}
|
|
1812
|
-
//
|
|
1813
|
-
// Collection
|
|
1814
|
-
//
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
* Add an item to the collection (alias for register)
|
|
1818
|
-
*
|
|
1819
|
-
* This method is part of the Collection interface.
|
|
1820
|
-
* It delegates to register() to ensure validation hooks are called.
|
|
1821
|
-
*
|
|
1822
|
-
* Time Complexity: O(1) + validation time
|
|
1823
|
-
*
|
|
1824
|
-
* @param key - Unique identifier for the item
|
|
1825
|
-
* @param value - Item to add
|
|
1736
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1737
|
+
// Collection interface
|
|
1738
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1739
|
+
/**
|
|
1740
|
+
* @inheritdoc — delegates to {@link register} so hooks still fire.
|
|
1826
1741
|
*/
|
|
1827
1742
|
add(key, value) {
|
|
1828
1743
|
this.register(key, value);
|
|
1829
1744
|
}
|
|
1830
1745
|
/**
|
|
1831
|
-
*
|
|
1832
|
-
*
|
|
1833
|
-
*
|
|
1834
|
-
*
|
|
1835
|
-
* - Returns undefined if no default item was configured
|
|
1836
|
-
*
|
|
1837
|
-
* Time Complexity: O(1)
|
|
1838
|
-
*
|
|
1746
|
+
* Retrieve an item by key.
|
|
1747
|
+
*
|
|
1748
|
+
* Falls back to {@link defaultItem} when the key is not found.
|
|
1749
|
+
*
|
|
1839
1750
|
* @param key - Item identifier
|
|
1840
|
-
* @returns
|
|
1841
|
-
*
|
|
1842
|
-
* @example
|
|
1843
|
-
* ```typescript
|
|
1844
|
-
* const theme = registry.get('blue');
|
|
1845
|
-
* ```
|
|
1751
|
+
* @returns The stored value, the default item, or `undefined`
|
|
1846
1752
|
*/
|
|
1847
1753
|
get(key) {
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
return this.defaultItem;
|
|
1853
|
-
}
|
|
1854
|
-
/**
|
|
1855
|
-
* Get all items in the registry
|
|
1856
|
-
*
|
|
1857
|
-
* Returns an array containing all items in the registry.
|
|
1858
|
-
* The order of items depends on the collection implementation
|
|
1859
|
-
* (MapCollection maintains insertion order).
|
|
1860
|
-
*
|
|
1861
|
-
* Time Complexity: O(n) where n is the number of items
|
|
1862
|
-
*
|
|
1863
|
-
* @returns Array of all items in the registry
|
|
1864
|
-
*
|
|
1865
|
-
* @example
|
|
1866
|
-
* ```typescript
|
|
1867
|
-
* const allThemes = registry.getAll();
|
|
1868
|
-
* ```
|
|
1754
|
+
return this.storage.get(key) ?? this.defaultItem;
|
|
1755
|
+
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Return every stored value in insertion order.
|
|
1869
1758
|
*/
|
|
1870
1759
|
getAll() {
|
|
1871
|
-
return this.
|
|
1872
|
-
}
|
|
1873
|
-
/**
|
|
1874
|
-
*
|
|
1875
|
-
*
|
|
1876
|
-
* Returns an array containing all keys in the registry.
|
|
1877
|
-
* Useful for iteration or checking what items are registered.
|
|
1878
|
-
*
|
|
1879
|
-
* Time Complexity: O(n) where n is the number of items
|
|
1880
|
-
*
|
|
1881
|
-
* @returns Array of all keys in the registry
|
|
1882
|
-
*
|
|
1883
|
-
* @example
|
|
1884
|
-
* ```typescript
|
|
1885
|
-
* const keys = registry.getKeys();
|
|
1886
|
-
* ```
|
|
1760
|
+
return this.storage.values();
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* Return every registered key in insertion order.
|
|
1887
1764
|
*/
|
|
1888
1765
|
getKeys() {
|
|
1889
|
-
return this.
|
|
1890
|
-
}
|
|
1891
|
-
/**
|
|
1892
|
-
*
|
|
1893
|
-
*
|
|
1894
|
-
* Converts the registry to a plain JavaScript object (record)
|
|
1895
|
-
* with keys mapping to values. Useful for serialization.
|
|
1896
|
-
*
|
|
1897
|
-
* Time Complexity: O(n) where n is the number of items
|
|
1898
|
-
*
|
|
1899
|
-
* @returns Record object with keys mapping to values
|
|
1900
|
-
*
|
|
1901
|
-
* @example
|
|
1902
|
-
* ```typescript
|
|
1903
|
-
* const record = registry.getAsRecord();
|
|
1904
|
-
* ```
|
|
1766
|
+
return this.storage.keys();
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Convert the registry to a plain `Record<string, T>`.
|
|
1905
1770
|
*/
|
|
1906
1771
|
getAsRecord() {
|
|
1907
|
-
return this.
|
|
1908
|
-
}
|
|
1909
|
-
/**
|
|
1910
|
-
* Check
|
|
1911
|
-
*
|
|
1912
|
-
* Checks whether an item with the specified key exists in the registry.
|
|
1913
|
-
* Does not check the value, only the presence of the key.
|
|
1914
|
-
*
|
|
1915
|
-
* Time Complexity: O(1)
|
|
1916
|
-
*
|
|
1917
|
-
* @param key - Item identifier to check
|
|
1918
|
-
* @returns True if item is registered, false otherwise
|
|
1919
|
-
*
|
|
1920
|
-
* @example
|
|
1921
|
-
* ```typescript
|
|
1922
|
-
* if (registry.has('blue')) {
|
|
1923
|
-
* console.log('Blue theme exists');
|
|
1924
|
-
* }
|
|
1925
|
-
* ```
|
|
1772
|
+
return this.storage.toObject();
|
|
1773
|
+
}
|
|
1774
|
+
/**
|
|
1775
|
+
* Check whether a key exists.
|
|
1926
1776
|
*/
|
|
1927
1777
|
has(key) {
|
|
1928
|
-
return this.
|
|
1778
|
+
return this.storage.has(key);
|
|
1929
1779
|
}
|
|
1930
1780
|
/**
|
|
1931
|
-
* Remove an item
|
|
1932
|
-
*
|
|
1933
|
-
*
|
|
1934
|
-
* Returns true if the item was removed, false if it didn't exist.
|
|
1935
|
-
*
|
|
1936
|
-
* Time Complexity: O(1)
|
|
1937
|
-
*
|
|
1938
|
-
* @param key - Item identifier to remove
|
|
1939
|
-
* @returns True if item was removed, false if it didn't exist
|
|
1940
|
-
*
|
|
1941
|
-
* @example
|
|
1942
|
-
* ```typescript
|
|
1943
|
-
* const removed = registry.remove('blue');
|
|
1944
|
-
* ```
|
|
1781
|
+
* Remove an item by key.
|
|
1782
|
+
*
|
|
1783
|
+
* @returns `true` if the key existed and was removed
|
|
1945
1784
|
*/
|
|
1946
1785
|
remove(key) {
|
|
1947
|
-
return this.
|
|
1786
|
+
return this.storage.delete(key);
|
|
1948
1787
|
}
|
|
1949
1788
|
/**
|
|
1950
|
-
*
|
|
1951
|
-
*
|
|
1952
|
-
* Removes all items from the registry, leaving it empty.
|
|
1953
|
-
* This operation is irreversible.
|
|
1954
|
-
*
|
|
1955
|
-
* Time Complexity: O(1)
|
|
1956
|
-
*
|
|
1957
|
-
* @example
|
|
1958
|
-
* ```typescript
|
|
1959
|
-
* registry.clear();
|
|
1960
|
-
* ```
|
|
1789
|
+
* Remove all items from the registry.
|
|
1961
1790
|
*/
|
|
1962
1791
|
clear() {
|
|
1963
|
-
this.
|
|
1964
|
-
}
|
|
1965
|
-
/**
|
|
1966
|
-
* Get the number of items in the registry
|
|
1967
|
-
*
|
|
1968
|
-
* Returns the total count of items currently registered.
|
|
1969
|
-
*
|
|
1970
|
-
* Time Complexity: O(1)
|
|
1971
|
-
*
|
|
1972
|
-
* @returns Number of items in the registry
|
|
1973
|
-
*
|
|
1974
|
-
* @example
|
|
1975
|
-
* ```typescript
|
|
1976
|
-
* console.log(registry.size()); // 2
|
|
1977
|
-
* ```
|
|
1978
|
-
*/
|
|
1979
|
-
size() {
|
|
1980
|
-
return this.collection.size();
|
|
1981
|
-
}
|
|
1982
|
-
/**
|
|
1983
|
-
* Check if the registry is empty
|
|
1984
|
-
*
|
|
1985
|
-
* Returns true if the registry contains no items, false otherwise.
|
|
1986
|
-
* This is a convenience method equivalent to checking if size() === 0.
|
|
1987
|
-
*
|
|
1988
|
-
* Time Complexity: O(1)
|
|
1989
|
-
*
|
|
1990
|
-
* @returns True if registry has no items, false otherwise
|
|
1991
|
-
*
|
|
1992
|
-
* @example
|
|
1993
|
-
* ```typescript
|
|
1994
|
-
* console.log(registry.isEmpty()); // true
|
|
1995
|
-
* ```
|
|
1996
|
-
*/
|
|
1997
|
-
isEmpty() {
|
|
1998
|
-
return this.collection.isEmpty();
|
|
1792
|
+
this.storage.clear();
|
|
1999
1793
|
}
|
|
2000
1794
|
/**
|
|
2001
|
-
*
|
|
2002
|
-
*
|
|
2003
|
-
* Executes a callback function for each item in the registry.
|
|
2004
|
-
* Items are iterated in insertion order (for MapCollection).
|
|
2005
|
-
*
|
|
2006
|
-
* Time Complexity: O(n) where n is the number of items
|
|
2007
|
-
*
|
|
2008
|
-
* @param callback - Function to call for each item (value, key)
|
|
2009
|
-
*
|
|
2010
|
-
* @example
|
|
2011
|
-
* ```typescript
|
|
2012
|
-
* registry.forEach((theme, key) => {
|
|
2013
|
-
* console.log(`${key}: ${theme.name}`);
|
|
2014
|
-
* });
|
|
2015
|
-
* ```
|
|
1795
|
+
* Return the number of registered items.
|
|
2016
1796
|
*/
|
|
2017
|
-
|
|
2018
|
-
this.
|
|
2019
|
-
}
|
|
2020
|
-
/**
|
|
2021
|
-
* Map over all items in the registry
|
|
2022
|
-
*
|
|
2023
|
-
* Transforms each item in the registry using a callback function
|
|
2024
|
-
* and returns an array of the transformed values.
|
|
2025
|
-
*
|
|
2026
|
-
* Time Complexity: O(n) where n is the number of items
|
|
2027
|
-
*
|
|
2028
|
-
* @template U - The type of the transformed items
|
|
2029
|
-
* @param callback - Function to transform each item (value, key) => U
|
|
2030
|
-
* @returns Array of transformed items
|
|
2031
|
-
*
|
|
2032
|
-
* @example
|
|
2033
|
-
* ```typescript
|
|
2034
|
-
* const names = registry.map(theme => theme.name);
|
|
2035
|
-
* ```
|
|
2036
|
-
*/
|
|
2037
|
-
map(callback) {
|
|
2038
|
-
return this.collection.map(callback);
|
|
2039
|
-
}
|
|
2040
|
-
/**
|
|
2041
|
-
* Filter items in the registry
|
|
2042
|
-
*
|
|
2043
|
-
* Returns an array of items that pass the test implemented by the
|
|
2044
|
-
* provided predicate function.
|
|
2045
|
-
*
|
|
2046
|
-
* Time Complexity: O(n) where n is the number of items
|
|
2047
|
-
*
|
|
2048
|
-
* @param predicate - Function to test each item (value, key) => boolean
|
|
2049
|
-
* @returns Array of items that pass the test
|
|
2050
|
-
*
|
|
2051
|
-
* @example
|
|
2052
|
-
* ```typescript
|
|
2053
|
-
* const darkThemes = registry.filter(theme => theme.isDark);
|
|
2054
|
-
* ```
|
|
2055
|
-
*/
|
|
2056
|
-
filter(predicate) {
|
|
2057
|
-
return this.collection.filter(predicate);
|
|
2058
|
-
}
|
|
2059
|
-
/**
|
|
2060
|
-
* Find an item in the registry
|
|
2061
|
-
*
|
|
2062
|
-
* Returns the first item that satisfies the provided predicate function.
|
|
2063
|
-
* Returns undefined if no item passes the test.
|
|
2064
|
-
*
|
|
2065
|
-
* Time Complexity: O(n) worst case, O(1) best case
|
|
2066
|
-
*
|
|
2067
|
-
* @param predicate - Function to test each item (value, key) => boolean
|
|
2068
|
-
* @returns First item that passes the test, or undefined
|
|
2069
|
-
*
|
|
2070
|
-
* @example
|
|
2071
|
-
* ```typescript
|
|
2072
|
-
* const defaultTheme = registry.find(theme => theme.isDefault);
|
|
2073
|
-
* ```
|
|
2074
|
-
*/
|
|
2075
|
-
find(predicate) {
|
|
2076
|
-
return this.collection.find(predicate);
|
|
1797
|
+
size() {
|
|
1798
|
+
return this.storage.size();
|
|
2077
1799
|
}
|
|
2078
|
-
};
|
|
2079
|
-
|
|
2080
|
-
// src/facades/facade.ts
|
|
2081
|
-
import { getModuleContainer } from "@abdokouta/react-di";
|
|
2082
|
-
|
|
2083
|
-
// src/facades/facade.interface.ts
|
|
2084
|
-
function isFake(obj) {
|
|
2085
|
-
return typeof obj === "object" && obj !== null && "__isFake" in obj && obj.__isFake === true;
|
|
2086
|
-
}
|
|
2087
|
-
|
|
2088
|
-
// src/facades/facade.ts
|
|
2089
|
-
var Facade = class {
|
|
2090
1800
|
/**
|
|
2091
|
-
*
|
|
2092
|
-
*
|
|
2093
|
-
* Useful for testing - swap the real service with a mock or fake.
|
|
2094
|
-
*
|
|
2095
|
-
* @param instance - Instance to swap in
|
|
2096
|
-
*
|
|
2097
|
-
* @example
|
|
2098
|
-
* ```typescript
|
|
2099
|
-
* // In tests
|
|
2100
|
-
* const mockLogger = { info: vi.fn(), error: vi.fn() };
|
|
2101
|
-
* Log.swap(mockLogger);
|
|
2102
|
-
*
|
|
2103
|
-
* // Now Log.info() calls mockLogger.info()
|
|
2104
|
-
* Log.info('test');
|
|
2105
|
-
* expect(mockLogger.info).toHaveBeenCalledWith('test');
|
|
2106
|
-
* ```
|
|
1801
|
+
* Return `true` when the registry is empty.
|
|
2107
1802
|
*/
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
const key = this.getAccessorKey(accessor);
|
|
2111
|
-
this.resolvedInstance.set(key, instance);
|
|
1803
|
+
isEmpty() {
|
|
1804
|
+
return this.storage.isEmpty();
|
|
2112
1805
|
}
|
|
2113
1806
|
/**
|
|
2114
|
-
*
|
|
2115
|
-
*
|
|
2116
|
-
* @returns True if the current instance is a Fake
|
|
2117
|
-
*
|
|
2118
|
-
* @example
|
|
2119
|
-
* ```typescript
|
|
2120
|
-
* if (Log.isFake()) {
|
|
2121
|
-
* console.log('Using fake logger');
|
|
2122
|
-
* }
|
|
2123
|
-
* ```
|
|
1807
|
+
* Iterate over every entry in insertion order.
|
|
2124
1808
|
*/
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
return instance !== void 0 && isFake(instance);
|
|
1809
|
+
forEach(callback) {
|
|
1810
|
+
this.storage.each((value, key) => {
|
|
1811
|
+
callback(value, key);
|
|
1812
|
+
});
|
|
2130
1813
|
}
|
|
2131
1814
|
/**
|
|
2132
|
-
*
|
|
2133
|
-
*
|
|
2134
|
-
* Resolves and returns the actual service instance.
|
|
2135
|
-
*
|
|
2136
|
-
* @returns The resolved service instance
|
|
1815
|
+
* Map every entry to a new value and return the results as an array.
|
|
2137
1816
|
*/
|
|
2138
|
-
|
|
2139
|
-
|
|
1817
|
+
map(callback) {
|
|
1818
|
+
const result = [];
|
|
1819
|
+
this.storage.each((value, key) => {
|
|
1820
|
+
result.push(callback(value, key));
|
|
1821
|
+
});
|
|
1822
|
+
return result;
|
|
2140
1823
|
}
|
|
2141
1824
|
/**
|
|
2142
|
-
*
|
|
2143
|
-
*
|
|
2144
|
-
* Subclasses MUST override this method to specify which service
|
|
2145
|
-
* the facade represents.
|
|
2146
|
-
*
|
|
2147
|
-
* @returns Service identifier (string, symbol, or class)
|
|
2148
|
-
* @throws Error if not implemented
|
|
2149
|
-
*
|
|
2150
|
-
* @example
|
|
2151
|
-
* ```typescript
|
|
2152
|
-
* class Log extends Facade {
|
|
2153
|
-
* protected static getFacadeAccessor(): ServiceIdentifier {
|
|
2154
|
-
* return LoggerService; // or 'logger' string token
|
|
2155
|
-
* }
|
|
2156
|
-
* }
|
|
2157
|
-
* ```
|
|
1825
|
+
* Return all values whose entries satisfy the predicate.
|
|
2158
1826
|
*/
|
|
2159
|
-
|
|
2160
|
-
|
|
1827
|
+
filter(predicate) {
|
|
1828
|
+
const result = [];
|
|
1829
|
+
this.storage.each((value, key) => {
|
|
1830
|
+
if (predicate(value, key)) {
|
|
1831
|
+
result.push(value);
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1834
|
+
return result;
|
|
2161
1835
|
}
|
|
2162
1836
|
/**
|
|
2163
|
-
*
|
|
1837
|
+
* Return the first value whose entry satisfies the predicate.
|
|
2164
1838
|
*/
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
return accessor.name || accessor.toString();
|
|
2168
|
-
}
|
|
2169
|
-
return accessor;
|
|
1839
|
+
find(predicate) {
|
|
1840
|
+
return this.storage.first(predicate);
|
|
2170
1841
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1844
|
+
// src/managers/multiple-instance-manager.ts
|
|
1845
|
+
var MultipleInstanceManager = class {
|
|
1846
|
+
constructor() {
|
|
1847
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1848
|
+
// State
|
|
1849
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1850
|
+
/**
|
|
1851
|
+
* Resolved instances, keyed by instance name.
|
|
1852
|
+
* Instances are created once and reused on subsequent calls.
|
|
1853
|
+
*/
|
|
1854
|
+
__publicField(this, "instances", /* @__PURE__ */ new Map());
|
|
1855
|
+
/**
|
|
1856
|
+
* Custom driver creators registered via `extend()`.
|
|
1857
|
+
* Keyed by driver name.
|
|
1858
|
+
*/
|
|
1859
|
+
__publicField(this, "customCreators", /* @__PURE__ */ new Map());
|
|
1860
|
+
/**
|
|
1861
|
+
* The config key that identifies the driver.
|
|
1862
|
+
* Override in subclasses if your config uses a different field name.
|
|
1863
|
+
*
|
|
1864
|
+
* @default 'driver'
|
|
1865
|
+
*/
|
|
1866
|
+
__publicField(this, "driverKey", "driver");
|
|
1867
|
+
}
|
|
1868
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1869
|
+
// Public API
|
|
1870
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1871
|
+
/**
|
|
1872
|
+
* Get an instance by name.
|
|
2173
1873
|
*
|
|
2174
|
-
*
|
|
2175
|
-
*
|
|
2176
|
-
*/
|
|
2177
|
-
static resolveFacadeInstance(identifier) {
|
|
2178
|
-
const key = this.getAccessorKey(identifier);
|
|
2179
|
-
if (this.resolvedInstance.has(key)) {
|
|
2180
|
-
return this.resolvedInstance.get(key);
|
|
2181
|
-
}
|
|
2182
|
-
const container = this.getContainer();
|
|
2183
|
-
if (!container) {
|
|
2184
|
-
throw new Error(
|
|
2185
|
-
`Unable to resolve facade instance. Module not set. Call Facade.setFacadeModule(YourModule) first.`
|
|
2186
|
-
);
|
|
2187
|
-
}
|
|
2188
|
-
const instance = container.get(identifier);
|
|
2189
|
-
if (this.cached) {
|
|
2190
|
-
this.resolvedInstance.set(key, instance);
|
|
2191
|
-
}
|
|
2192
|
-
return instance;
|
|
2193
|
-
}
|
|
2194
|
-
/**
|
|
2195
|
-
* Get the module container
|
|
1874
|
+
* Returns a cached instance if available, otherwise resolves and caches it.
|
|
1875
|
+
* If no name is provided, returns the default instance.
|
|
2196
1876
|
*
|
|
2197
|
-
* @
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
1877
|
+
* @param name - Instance name (uses default if omitted)
|
|
1878
|
+
* @returns The resolved instance
|
|
1879
|
+
* @throws Error if the instance is not configured
|
|
1880
|
+
*/
|
|
1881
|
+
instance(name) {
|
|
1882
|
+
const instanceName = name ?? this.getDefaultInstance();
|
|
1883
|
+
const existing = this.instances.get(instanceName);
|
|
1884
|
+
if (existing) {
|
|
1885
|
+
return existing;
|
|
2202
1886
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
}
|
|
2207
|
-
return null;
|
|
1887
|
+
const resolved = this.resolve(instanceName);
|
|
1888
|
+
this.instances.set(instanceName, resolved);
|
|
1889
|
+
return resolved;
|
|
2208
1890
|
}
|
|
2209
1891
|
/**
|
|
2210
|
-
*
|
|
1892
|
+
* Register a custom driver creator.
|
|
2211
1893
|
*
|
|
2212
|
-
*
|
|
2213
|
-
*/
|
|
2214
|
-
static clearResolvedInstance(name) {
|
|
2215
|
-
const key = name ?? this.getAccessorKey(this.getFacadeAccessor());
|
|
2216
|
-
this.resolvedInstance.delete(key);
|
|
2217
|
-
}
|
|
2218
|
-
/**
|
|
2219
|
-
* Clear all resolved instances
|
|
1894
|
+
* Custom creators take priority over built-in drivers.
|
|
2220
1895
|
*
|
|
2221
|
-
*
|
|
1896
|
+
* @param driver - Driver name
|
|
1897
|
+
* @param creator - Factory function that creates an instance from config
|
|
1898
|
+
* @returns this (for chaining)
|
|
2222
1899
|
*/
|
|
2223
|
-
|
|
2224
|
-
this.
|
|
1900
|
+
extend(driver, creator) {
|
|
1901
|
+
this.customCreators.set(driver, creator);
|
|
1902
|
+
return this;
|
|
2225
1903
|
}
|
|
2226
1904
|
/**
|
|
2227
|
-
*
|
|
1905
|
+
* Remove a cached instance, forcing re-creation on next access.
|
|
2228
1906
|
*
|
|
2229
|
-
* @
|
|
1907
|
+
* @param name - Instance name (uses default if omitted)
|
|
1908
|
+
* @returns this (for chaining)
|
|
2230
1909
|
*/
|
|
2231
|
-
|
|
2232
|
-
|
|
1910
|
+
forgetInstance(name) {
|
|
1911
|
+
const instanceName = name ?? this.getDefaultInstance();
|
|
1912
|
+
this.instances.delete(instanceName);
|
|
1913
|
+
return this;
|
|
2233
1914
|
}
|
|
2234
1915
|
/**
|
|
2235
|
-
*
|
|
2236
|
-
*
|
|
2237
|
-
* Must be called during application bootstrap to enable facades.
|
|
2238
|
-
* Call this AFTER Inversiland.run() or Container.configure().build().
|
|
2239
|
-
*
|
|
2240
|
-
* @param module - The root module class
|
|
2241
|
-
*
|
|
2242
|
-
* @example
|
|
2243
|
-
* ```typescript
|
|
2244
|
-
* // In your app bootstrap (main.tsx)
|
|
2245
|
-
* import { Facade } from '@abdokouta/react-support';
|
|
2246
|
-
* import { Container, ContainerProvider } from '@abdokouta/react-di';
|
|
2247
|
-
* import { AppModule } from './app.module';
|
|
2248
|
-
*
|
|
2249
|
-
* // Initialize container
|
|
2250
|
-
* Container.configure().withModule(AppModule).withDefaults().build();
|
|
2251
|
-
*
|
|
2252
|
-
* // Set facade module
|
|
2253
|
-
* Facade.setFacadeModule(AppModule);
|
|
2254
|
-
*
|
|
2255
|
-
* // Now facades work anywhere
|
|
2256
|
-
* ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
2257
|
-
* <ContainerProvider module={AppModule}>
|
|
2258
|
-
* <App />
|
|
2259
|
-
* </ContainerProvider>
|
|
2260
|
-
* );
|
|
2261
|
-
* ```
|
|
1916
|
+
* Remove all cached instances.
|
|
2262
1917
|
*/
|
|
2263
|
-
|
|
2264
|
-
this.
|
|
2265
|
-
this.container = null;
|
|
1918
|
+
purge() {
|
|
1919
|
+
this.instances.clear();
|
|
2266
1920
|
}
|
|
2267
1921
|
/**
|
|
2268
|
-
*
|
|
1922
|
+
* Check if an instance has been resolved and cached.
|
|
2269
1923
|
*
|
|
2270
|
-
* @param
|
|
1924
|
+
* @param name - Instance name
|
|
2271
1925
|
*/
|
|
2272
|
-
|
|
2273
|
-
this.
|
|
1926
|
+
hasResolvedInstance(name) {
|
|
1927
|
+
return this.instances.has(name);
|
|
2274
1928
|
}
|
|
2275
|
-
// ============================================================================
|
|
2276
|
-
// Legacy API (for compatibility with FacadeApplication interface)
|
|
2277
|
-
// ============================================================================
|
|
2278
1929
|
/**
|
|
2279
|
-
*
|
|
1930
|
+
* Get all resolved instance names.
|
|
2280
1931
|
*/
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
this.container = {
|
|
2284
|
-
get: (id) => app.get(id)
|
|
2285
|
-
};
|
|
2286
|
-
} else {
|
|
2287
|
-
this.container = null;
|
|
2288
|
-
}
|
|
1932
|
+
getResolvedInstances() {
|
|
1933
|
+
return Array.from(this.instances.keys());
|
|
2289
1934
|
}
|
|
1935
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1936
|
+
// Resolution (private)
|
|
1937
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
2290
1938
|
/**
|
|
2291
|
-
*
|
|
1939
|
+
* Resolve an instance by name.
|
|
1940
|
+
*
|
|
1941
|
+
* 1. Reads config via `getInstanceConfig()` (from injected config)
|
|
1942
|
+
* 2. Extracts the driver name from the config
|
|
1943
|
+
* 3. Checks custom creators first
|
|
1944
|
+
* 4. Falls back to `createDriver()`
|
|
1945
|
+
*
|
|
1946
|
+
* @param name - Instance name
|
|
1947
|
+
* @returns A new instance
|
|
2292
1948
|
*/
|
|
2293
|
-
|
|
2294
|
-
const
|
|
2295
|
-
if (!
|
|
2296
|
-
|
|
2297
|
-
get: (abstract) => container.get(abstract)
|
|
2298
|
-
};
|
|
2299
|
-
}
|
|
2300
|
-
};
|
|
2301
|
-
/**
|
|
2302
|
-
* The root module class for resolving services
|
|
2303
|
-
*/
|
|
2304
|
-
Facade.moduleClass = null;
|
|
2305
|
-
/**
|
|
2306
|
-
* The module container instance (cached)
|
|
2307
|
-
*/
|
|
2308
|
-
Facade.container = null;
|
|
2309
|
-
/**
|
|
2310
|
-
* The resolved object instances
|
|
2311
|
-
*
|
|
2312
|
-
* Caches resolved instances by their accessor key for performance.
|
|
2313
|
-
*/
|
|
2314
|
-
Facade.resolvedInstance = /* @__PURE__ */ new Map();
|
|
2315
|
-
/**
|
|
2316
|
-
* Indicates if the resolved instance should be cached
|
|
2317
|
-
*
|
|
2318
|
-
* Set to false in subclasses to always resolve fresh instances.
|
|
2319
|
-
*/
|
|
2320
|
-
Facade.cached = true;
|
|
2321
|
-
|
|
2322
|
-
// src/facades/create-facade.ts
|
|
2323
|
-
import { getModuleContainer as getModuleContainer2 } from "@abdokouta/react-di";
|
|
2324
|
-
function createFacade(options) {
|
|
2325
|
-
const { accessor, cached = true } = options;
|
|
2326
|
-
class ConcreteFacade extends Facade {
|
|
2327
|
-
static getFacadeAccessor() {
|
|
2328
|
-
return accessor;
|
|
1949
|
+
resolve(name) {
|
|
1950
|
+
const config = this.getInstanceConfig(name);
|
|
1951
|
+
if (!config) {
|
|
1952
|
+
throw new Error(`Instance [${name}] is not defined.`);
|
|
2329
1953
|
}
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
get(target, prop, receiver) {
|
|
2334
|
-
if (prop in target) {
|
|
2335
|
-
const value = Reflect.get(target, prop, receiver);
|
|
2336
|
-
if (typeof value === "function") {
|
|
2337
|
-
return value.bind(target);
|
|
2338
|
-
}
|
|
2339
|
-
return value;
|
|
2340
|
-
}
|
|
2341
|
-
return (...args) => {
|
|
2342
|
-
const instance = target.getFacadeRoot();
|
|
2343
|
-
if (!instance) {
|
|
2344
|
-
throw new Error(
|
|
2345
|
-
`A facade root has not been set. Call Facade.setFacadeModule() first.`
|
|
2346
|
-
);
|
|
2347
|
-
}
|
|
2348
|
-
const method = instance[prop];
|
|
2349
|
-
if (typeof method !== "function") {
|
|
2350
|
-
throw new Error(
|
|
2351
|
-
`Method "${String(prop)}" does not exist on the facade root.`
|
|
2352
|
-
);
|
|
2353
|
-
}
|
|
2354
|
-
return method.apply(instance, args);
|
|
2355
|
-
};
|
|
1954
|
+
const driver = config[this.driverKey];
|
|
1955
|
+
if (!driver) {
|
|
1956
|
+
throw new Error(`Instance [${name}] does not specify a "${this.driverKey}".`);
|
|
2356
1957
|
}
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
function createFacadeClass(accessor) {
|
|
2361
|
-
return class extends Facade {
|
|
2362
|
-
static getFacadeAccessor() {
|
|
2363
|
-
return accessor;
|
|
1958
|
+
const customCreator = this.customCreators.get(driver);
|
|
1959
|
+
if (customCreator) {
|
|
1960
|
+
return customCreator(config);
|
|
2364
1961
|
}
|
|
2365
|
-
|
|
2366
|
-
}
|
|
2367
|
-
|
|
2368
|
-
return getModuleContainer2(moduleClass);
|
|
2369
|
-
}
|
|
1962
|
+
return this.createDriver(driver, config);
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
2370
1965
|
export {
|
|
2371
1966
|
BaseRegistry,
|
|
2372
1967
|
Collection,
|
|
2373
|
-
Facade,
|
|
2374
1968
|
MapCollection,
|
|
1969
|
+
MultipleInstanceManager,
|
|
2375
1970
|
SetCollection,
|
|
2376
1971
|
Str,
|
|
2377
1972
|
collect,
|
|
2378
1973
|
collectMap,
|
|
2379
|
-
collectSet
|
|
2380
|
-
createFacade,
|
|
2381
|
-
createFacadeClass,
|
|
2382
|
-
getContainerFromModule,
|
|
2383
|
-
isFake
|
|
1974
|
+
collectSet
|
|
2384
1975
|
};
|
|
2385
1976
|
//# sourceMappingURL=index.mjs.map
|