mutts 1.0.1 → 1.0.2

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.
Files changed (60) hide show
  1. package/README.md +24 -2
  2. package/dist/chunks/_tslib-C-cuVLvZ.js +73 -0
  3. package/dist/chunks/_tslib-C-cuVLvZ.js.map +1 -0
  4. package/dist/chunks/_tslib-CMEnd0VE.esm.js +68 -0
  5. package/dist/chunks/_tslib-CMEnd0VE.esm.js.map +1 -0
  6. package/dist/chunks/{decorator-8qjFb7dw.js → decorator-D4DU97Zg.js} +70 -4
  7. package/dist/chunks/decorator-D4DU97Zg.js.map +1 -0
  8. package/dist/chunks/{decorator-AbRkXM5O.esm.js → decorator-GnHw1Az7.esm.js} +67 -5
  9. package/dist/chunks/decorator-GnHw1Az7.esm.js.map +1 -0
  10. package/dist/chunks/index-DBScoeCX.esm.js +1960 -0
  11. package/dist/chunks/index-DBScoeCX.esm.js.map +1 -0
  12. package/dist/chunks/index-DOTmXL89.js +1983 -0
  13. package/dist/chunks/index-DOTmXL89.js.map +1 -0
  14. package/dist/decorator.d.ts +57 -0
  15. package/dist/decorator.esm.js +1 -1
  16. package/dist/decorator.js +1 -1
  17. package/dist/destroyable.d.ts +42 -0
  18. package/dist/destroyable.esm.js +19 -1
  19. package/dist/destroyable.esm.js.map +1 -1
  20. package/dist/destroyable.js +19 -1
  21. package/dist/destroyable.js.map +1 -1
  22. package/dist/eventful.d.ts +10 -1
  23. package/dist/eventful.esm.js +5 -27
  24. package/dist/eventful.esm.js.map +1 -1
  25. package/dist/eventful.js +15 -37
  26. package/dist/eventful.js.map +1 -1
  27. package/dist/index.d.ts +52 -3
  28. package/dist/index.esm.js +3 -2
  29. package/dist/index.esm.js.map +1 -1
  30. package/dist/index.js +17 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/indexable.d.ts +26 -0
  33. package/dist/indexable.esm.js +6 -0
  34. package/dist/indexable.esm.js.map +1 -1
  35. package/dist/indexable.js +6 -0
  36. package/dist/indexable.js.map +1 -1
  37. package/dist/mutts.umd.js +1 -1
  38. package/dist/mutts.umd.js.map +1 -1
  39. package/dist/mutts.umd.min.js +1 -1
  40. package/dist/mutts.umd.min.js.map +1 -1
  41. package/dist/promiseChain.d.ts +10 -0
  42. package/dist/promiseChain.esm.js +6 -0
  43. package/dist/promiseChain.esm.js.map +1 -1
  44. package/dist/promiseChain.js +6 -0
  45. package/dist/promiseChain.js.map +1 -1
  46. package/dist/reactive.d.ts +255 -18
  47. package/dist/reactive.esm.js +4 -1458
  48. package/dist/reactive.esm.js.map +1 -1
  49. package/dist/reactive.js +29 -1471
  50. package/dist/reactive.js.map +1 -1
  51. package/dist/std-decorators.d.ts +35 -0
  52. package/dist/std-decorators.esm.js +36 -1
  53. package/dist/std-decorators.esm.js.map +1 -1
  54. package/dist/std-decorators.js +36 -1
  55. package/dist/std-decorators.js.map +1 -1
  56. package/docs/mixin.md +229 -0
  57. package/docs/reactive.md +7739 -882
  58. package/package.json +1 -1
  59. package/dist/chunks/decorator-8qjFb7dw.js.map +0 -1
  60. package/dist/chunks/decorator-AbRkXM5O.esm.js.map +0 -1
package/docs/mixin.md ADDED
@@ -0,0 +1,229 @@
1
+ # Mixin System
2
+
3
+ The mixin system provides a powerful way to create reusable functionality that can be applied to classes either as base classes or as mixin functions.
4
+
5
+ ## Overview
6
+
7
+ The `mixin()` function creates a mixin that can be used in two ways:
8
+ 1. **As a base class** - `class MyClass extends MyMixin`
9
+ 2. **As a mixin function** - `class MyClass extends MyMixin(SomeBase)`
10
+
11
+ ## Basic Usage
12
+
13
+ ### Creating a Mixin
14
+
15
+ ```typescript
16
+ import { mixin } from 'mutts/mixin'
17
+
18
+ const CounterMixin = mixin((base) => {
19
+ return class extends base {
20
+ count = 0
21
+
22
+ increment() {
23
+ this.count++
24
+ }
25
+
26
+ getCount() {
27
+ return this.count
28
+ }
29
+ }
30
+ })
31
+ ```
32
+
33
+ ### Using as Base Class
34
+
35
+ ```typescript
36
+ class MyClass extends CounterMixin {
37
+ name = 'MyClass'
38
+
39
+ greet() {
40
+ return `Hello, I'm ${this.name} with count ${this.count}`
41
+ }
42
+ }
43
+
44
+ const instance = new MyClass()
45
+ instance.increment()
46
+ console.log(instance.greet()) // "Hello, I'm MyClass with count 1"
47
+ ```
48
+
49
+ ### Using as Mixin Function
50
+
51
+ ```typescript
52
+ class BaseClass {
53
+ value = 42
54
+ }
55
+
56
+ class MyClass extends CounterMixin(BaseClass) {
57
+ name = 'MyClass'
58
+ }
59
+
60
+ const instance = new MyClass()
61
+ console.log(instance.value) // 42 (from BaseClass)
62
+ console.log(instance.count) // 0 (from CounterMixin)
63
+ instance.increment()
64
+ console.log(instance.getCount()) // 1
65
+ ```
66
+
67
+ ## Advanced Examples
68
+
69
+ ### Eventful Mixin
70
+
71
+ ```typescript
72
+ const EventfulMixin = mixin((base) => {
73
+ return class extends base {
74
+ #events = new Map()
75
+
76
+ on(event: string, callback: Function) {
77
+ if (!this.#events.has(event)) {
78
+ this.#events.set(event, [])
79
+ }
80
+ this.#events.get(event)!.push(callback)
81
+ }
82
+
83
+ emit(event: string, ...args: any[]) {
84
+ const callbacks = this.#events.get(event) || []
85
+ callbacks.forEach(cb => cb(...args))
86
+ }
87
+
88
+ off(event: string, callback?: Function) {
89
+ if (!callback) {
90
+ this.#events.delete(event)
91
+ return
92
+ }
93
+ const callbacks = this.#events.get(event) || []
94
+ this.#events.set(event, callbacks.filter(cb => cb !== callback))
95
+ }
96
+ }
97
+ })
98
+
99
+ // Use as base class
100
+ class EventEmitter extends EventfulMixin {
101
+ constructor(public name: string) {
102
+ super()
103
+ }
104
+ }
105
+
106
+ // Use as mixin
107
+ class GameObject extends EventfulMixin(BaseClass) {
108
+ constructor(public id: string) {
109
+ super()
110
+ }
111
+ }
112
+ ```
113
+
114
+ ### Combining Mixins
115
+
116
+ ```typescript
117
+ class BaseModel {
118
+ id = Math.random().toString(36)
119
+ }
120
+
121
+ class UserModel extends EventfulMixin(CounterMixin(BaseModel)) {
122
+ name = 'User'
123
+ email = 'user@example.com'
124
+
125
+ updateProfile(newName: string) {
126
+ this.name = newName
127
+ this.emit('profileUpdated', { name: newName })
128
+ this.increment()
129
+ }
130
+ }
131
+
132
+ const user = new UserModel()
133
+ user.on('profileUpdated', (data) => {
134
+ console.log('Profile updated:', data)
135
+ })
136
+
137
+ user.updateProfile('John Doe')
138
+ // Output: "Profile updated: { name: 'John Doe' }"
139
+ // user.count is now 1
140
+ ```
141
+
142
+ ## Caching
143
+
144
+ The mixin system automatically caches results to ensure that the same base class always returns the same mixed class. This provides:
145
+
146
+ - **Performance**: No repeated class creation
147
+ - **Identity**: Same base class always produces the same mixed class
148
+ - **Memory efficiency**: Automatic cleanup when base classes are garbage collected
149
+
150
+ ```typescript
151
+ const MixinA = mixin((base) => class extends base { prop = 'A' })
152
+ const MixinB = mixin((base) => class extends base { prop = 'B' })
153
+
154
+ class BaseClass {}
155
+
156
+ const Mixed1 = MixinA(BaseClass)
157
+ const Mixed2 = MixinA(BaseClass)
158
+
159
+ console.log(Mixed1 === Mixed2) // true - same reference due to caching
160
+ ```
161
+
162
+ ## Error Handling
163
+
164
+ The mixin system provides clear error messages for invalid usage:
165
+
166
+ ```typescript
167
+ const MyMixin = mixin((base) => class extends base {})
168
+
169
+ // ❌ Error: Mixin requires a base class
170
+ MyMixin()
171
+
172
+ // ❌ Error: Mixin requires a constructor function
173
+ MyMixin('not a function')
174
+
175
+ // ✅ Valid usage
176
+ MyMixin(SomeClass)
177
+ ```
178
+
179
+ ## Type Safety
180
+
181
+ The mixin system preserves TypeScript type information:
182
+
183
+ ```typescript
184
+ interface User {
185
+ name: string
186
+ email: string
187
+ }
188
+
189
+ const UserMixin = mixin((base) => {
190
+ return class extends base {
191
+ validateEmail(): boolean {
192
+ return this.email.includes('@')
193
+ }
194
+ }
195
+ })
196
+
197
+ class UserModel extends UserMixin {
198
+ name = ''
199
+ email = ''
200
+ }
201
+
202
+ const user = new UserModel()
203
+ user.validateEmail() // TypeScript knows this method exists
204
+ ```
205
+
206
+ ## Best Practices
207
+
208
+ 1. **Keep mixins focused**: Each mixin should provide a single, cohesive piece of functionality
209
+ 2. **Use descriptive names**: Make it clear what functionality the mixin provides
210
+ 3. **Document behavior**: Include JSDoc comments for mixin methods
211
+ 4. **Consider composition**: Combine multiple small mixins rather than creating one large mixin
212
+ 5. **Test thoroughly**: Mixins can have complex interactions, so comprehensive testing is important
213
+
214
+ ## Integration with MutTs
215
+
216
+ The mixin system is designed to work seamlessly with other MutTs features:
217
+
218
+ - **ReactiveBase**: Can be used as a mixin to add reactivity to any class
219
+ - **Eventful**: Can be used as a mixin to add event handling to any class
220
+ - **Destroyable**: Can be used as a mixin to add cleanup functionality to any class
221
+
222
+ This allows for powerful combinations like:
223
+
224
+ ```typescript
225
+ // Reactive + Eventful + Destroyable
226
+ class GameEntity extends Destroyable(Eventful(ReactiveBase(BaseClass))) {
227
+ // Your game entity with all capabilities
228
+ }
229
+ ```