storion 0.7.7 → 0.7.9
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 +125 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1453,6 +1453,126 @@ const myStore = store({
|
|
|
1453
1453
|
| Arguments | None | Supports extra args |
|
|
1454
1454
|
| Use case | Shared services | Configured instances |
|
|
1455
1455
|
|
|
1456
|
+
### Mixins (Reusable Logic)
|
|
1457
|
+
|
|
1458
|
+
Mixins let you compose reusable logic across stores and selectors.
|
|
1459
|
+
|
|
1460
|
+
**Store Mixin — reusable actions:**
|
|
1461
|
+
|
|
1462
|
+
```ts
|
|
1463
|
+
import { store, type StoreContext } from "storion";
|
|
1464
|
+
|
|
1465
|
+
// Define a reusable mixin
|
|
1466
|
+
const counterMixin = (ctx: StoreContext<{ count: number }>) => ({
|
|
1467
|
+
increment: () => ctx.state.count++,
|
|
1468
|
+
decrement: () => ctx.state.count--,
|
|
1469
|
+
reset: () => ctx.reset(),
|
|
1470
|
+
});
|
|
1471
|
+
|
|
1472
|
+
// Use in multiple stores
|
|
1473
|
+
const store1 = store({
|
|
1474
|
+
name: "counter1",
|
|
1475
|
+
state: { count: 0, label: "Counter 1" },
|
|
1476
|
+
setup: (ctx) => ({
|
|
1477
|
+
...ctx.mixin(counterMixin),
|
|
1478
|
+
setLabel: (label: string) => (ctx.state.label = label),
|
|
1479
|
+
}),
|
|
1480
|
+
});
|
|
1481
|
+
|
|
1482
|
+
const store2 = store({
|
|
1483
|
+
name: "counter2",
|
|
1484
|
+
state: { count: 100 },
|
|
1485
|
+
setup: (ctx) => ctx.mixin(counterMixin),
|
|
1486
|
+
});
|
|
1487
|
+
```
|
|
1488
|
+
|
|
1489
|
+
**Selector Mixin — reusable selector logic:**
|
|
1490
|
+
|
|
1491
|
+
```tsx
|
|
1492
|
+
import { useStore, type SelectorContext } from "storion/react";
|
|
1493
|
+
|
|
1494
|
+
// Define a reusable selector mixin
|
|
1495
|
+
const sumMixin = (
|
|
1496
|
+
ctx: SelectorContext,
|
|
1497
|
+
stores: StoreSpec<{ value: number }>[]
|
|
1498
|
+
) => {
|
|
1499
|
+
return stores.reduce((sum, spec) => {
|
|
1500
|
+
const [state] = ctx.get(spec);
|
|
1501
|
+
return sum + state.value;
|
|
1502
|
+
}, 0);
|
|
1503
|
+
};
|
|
1504
|
+
|
|
1505
|
+
function Dashboard() {
|
|
1506
|
+
const { total } = useStore((ctx) => ({
|
|
1507
|
+
total: ctx.mixin(sumMixin, [store1, store2, store3]),
|
|
1508
|
+
}));
|
|
1509
|
+
|
|
1510
|
+
return <div>Total: {total}</div>;
|
|
1511
|
+
}
|
|
1512
|
+
```
|
|
1513
|
+
|
|
1514
|
+
**Important: Mixins are NOT singletons**
|
|
1515
|
+
|
|
1516
|
+
Each call to `mixin()` creates a fresh instance. If you need singleton behavior **within the same store/selector scope**, wrap with memoize:
|
|
1517
|
+
|
|
1518
|
+
```ts
|
|
1519
|
+
import memoize from "lodash/memoize";
|
|
1520
|
+
import { store, type StoreContext } from "storion";
|
|
1521
|
+
|
|
1522
|
+
// Shared mixin - memoized to be singleton within same store setup
|
|
1523
|
+
const sharedLogicMixin = memoize((ctx: StoreContext<any>) => {
|
|
1524
|
+
console.log("sharedLogicMixin created"); // Only logs once per store!
|
|
1525
|
+
return {
|
|
1526
|
+
doSomething: () => console.log("shared logic"),
|
|
1527
|
+
};
|
|
1528
|
+
});
|
|
1529
|
+
|
|
1530
|
+
// Feature A mixin - uses sharedLogicMixin
|
|
1531
|
+
const featureAMixin = (ctx: StoreContext<any>) => {
|
|
1532
|
+
const shared = ctx.mixin(sharedLogicMixin); // Gets cached instance
|
|
1533
|
+
return {
|
|
1534
|
+
featureA: () => shared.doSomething(),
|
|
1535
|
+
};
|
|
1536
|
+
};
|
|
1537
|
+
|
|
1538
|
+
// Feature B mixin - also uses sharedLogicMixin
|
|
1539
|
+
const featureBMixin = (ctx: StoreContext<any>) => {
|
|
1540
|
+
const shared = ctx.mixin(sharedLogicMixin); // Gets SAME cached instance
|
|
1541
|
+
return {
|
|
1542
|
+
featureB: () => shared.doSomething(),
|
|
1543
|
+
};
|
|
1544
|
+
};
|
|
1545
|
+
|
|
1546
|
+
// Main store - composes both features
|
|
1547
|
+
const myStore = store({
|
|
1548
|
+
name: "myStore",
|
|
1549
|
+
state: { value: 0 },
|
|
1550
|
+
setup: (ctx) => {
|
|
1551
|
+
const featureA = ctx.mixin(featureAMixin);
|
|
1552
|
+
const featureB = ctx.mixin(featureBMixin);
|
|
1553
|
+
|
|
1554
|
+
// Both features share the same sharedLogicMixin instance!
|
|
1555
|
+
// featureA.featureA and featureB.featureB call the same shared.doSomething
|
|
1556
|
+
|
|
1557
|
+
return { ...featureA, ...featureB };
|
|
1558
|
+
},
|
|
1559
|
+
});
|
|
1560
|
+
```
|
|
1561
|
+
|
|
1562
|
+
**What happens:**
|
|
1563
|
+
|
|
1564
|
+
1. `featureAMixin` calls `mixin(sharedLogicMixin)` → creates instance, memoize caches it
|
|
1565
|
+
2. `featureBMixin` calls `mixin(sharedLogicMixin)` → returns cached instance
|
|
1566
|
+
3. Both features share the same `sharedLogicMixin` instance within this store
|
|
1567
|
+
|
|
1568
|
+
**When to use mixin vs service:**
|
|
1569
|
+
|
|
1570
|
+
| Pattern | Caching | Access to context | Use case |
|
|
1571
|
+
| -------------------- | ------------------------- | ---------------------- | ----------------------------------- |
|
|
1572
|
+
| `get(service)` | ✅ Global singleton | ❌ No StoreContext | Shared utilities, API clients |
|
|
1573
|
+
| `mixin(fn)` | ❌ Fresh each call | ✅ Full context access | Reusable actions, computed values |
|
|
1574
|
+
| `mixin(memoize(fn))` | ✅ Singleton (same scope) | ✅ Full context access | Shared logic across multiple mixins |
|
|
1575
|
+
|
|
1456
1576
|
### Equality Strategies
|
|
1457
1577
|
|
|
1458
1578
|
Storion supports equality checks at **two levels**, giving you fine-grained control over when updates happen.
|
|
@@ -1634,7 +1754,7 @@ const myStore = store({
|
|
|
1634
1754
|
|
|
1635
1755
|
### DevTools Integration
|
|
1636
1756
|
|
|
1637
|
-

|
|
1638
1758
|
|
|
1639
1759
|
```ts
|
|
1640
1760
|
import { devtools } from "storion/devtools";
|
|
@@ -1965,6 +2085,10 @@ fix(react): resolve hook issue
|
|
|
1965
2085
|
docs: update README
|
|
1966
2086
|
```
|
|
1967
2087
|
|
|
2088
|
+
### AI Assistance
|
|
2089
|
+
|
|
2090
|
+
For AI coding assistants, see [AI_GUIDE.md](./AI_GUIDE.md) for rules and patterns when generating Storion code.
|
|
2091
|
+
|
|
1968
2092
|
---
|
|
1969
2093
|
|
|
1970
2094
|
## License
|