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