mutts 1.0.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/README.md +150 -0
- package/dist/chunks/decorator-BXsign4Z.js +176 -0
- package/dist/chunks/decorator-BXsign4Z.js.map +1 -0
- package/dist/chunks/decorator-CPbZNnsX.esm.js +168 -0
- package/dist/chunks/decorator-CPbZNnsX.esm.js.map +1 -0
- package/dist/decorator.d.ts +50 -0
- package/dist/decorator.esm.js +2 -0
- package/dist/decorator.esm.js.map +1 -0
- package/dist/decorator.js +11 -0
- package/dist/decorator.js.map +1 -0
- package/dist/destroyable.d.ts +48 -0
- package/dist/destroyable.esm.js +91 -0
- package/dist/destroyable.esm.js.map +1 -0
- package/dist/destroyable.js +98 -0
- package/dist/destroyable.js.map +1 -0
- package/dist/eventful.d.ts +11 -0
- package/dist/eventful.esm.js +88 -0
- package/dist/eventful.esm.js.map +1 -0
- package/dist/eventful.js +90 -0
- package/dist/eventful.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.esm.js +7 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/indexable.d.ts +31 -0
- package/dist/indexable.esm.js +85 -0
- package/dist/indexable.esm.js.map +1 -0
- package/dist/indexable.js +89 -0
- package/dist/indexable.js.map +1 -0
- package/dist/mutts.umd.js +2 -0
- package/dist/mutts.umd.js.map +1 -0
- package/dist/mutts.umd.min.js +2 -0
- package/dist/mutts.umd.min.js.map +1 -0
- package/dist/promiseChain.d.ts +11 -0
- package/dist/promiseChain.esm.js +72 -0
- package/dist/promiseChain.esm.js.map +1 -0
- package/dist/promiseChain.js +74 -0
- package/dist/promiseChain.js.map +1 -0
- package/dist/reactive.d.ts +114 -0
- package/dist/reactive.esm.js +1455 -0
- package/dist/reactive.esm.js.map +1 -0
- package/dist/reactive.js +1472 -0
- package/dist/reactive.js.map +1 -0
- package/dist/std-decorators.d.ts +17 -0
- package/dist/std-decorators.esm.js +161 -0
- package/dist/std-decorators.esm.js.map +1 -0
- package/dist/std-decorators.js +169 -0
- package/dist/std-decorators.js.map +1 -0
- package/docs/decorator.md +300 -0
- package/docs/destroyable.md +294 -0
- package/docs/events.md +225 -0
- package/docs/indexable.md +561 -0
- package/docs/promiseChain.md +218 -0
- package/docs/reactive.md +2072 -0
- package/docs/std-decorators.md +558 -0
- package/package.json +132 -0
- package/src/decorator.test.ts +495 -0
- package/src/decorator.ts +205 -0
- package/src/destroyable.test.ts +155 -0
- package/src/destroyable.ts +158 -0
- package/src/eventful.test.ts +380 -0
- package/src/eventful.ts +69 -0
- package/src/index.ts +7 -0
- package/src/indexable.test.ts +388 -0
- package/src/indexable.ts +124 -0
- package/src/promiseChain.test.ts +201 -0
- package/src/promiseChain.ts +99 -0
- package/src/reactive/array.test.ts +923 -0
- package/src/reactive/array.ts +352 -0
- package/src/reactive/core.test.ts +1663 -0
- package/src/reactive/core.ts +866 -0
- package/src/reactive/index.ts +28 -0
- package/src/reactive/interface.test.ts +1477 -0
- package/src/reactive/interface.ts +231 -0
- package/src/reactive/map.test.ts +866 -0
- package/src/reactive/map.ts +162 -0
- package/src/reactive/set.test.ts +289 -0
- package/src/reactive/set.ts +142 -0
- package/src/std-decorators.test.ts +679 -0
- package/src/std-decorators.ts +182 -0
- package/src/utils.ts +52 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# PromiseChain
|
|
2
|
+
|
|
3
|
+
A TypeScript utility that transforms promises into chainable objects, allowing you to call methods directly on promise results without awaiting them first.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `promiseChain` module provides a way to work with promises in a more fluent, chainable manner. Instead of using `await` at every step, you can call methods directly on promise results and let the system handle the promise resolution automatically.
|
|
8
|
+
|
|
9
|
+
## API Reference
|
|
10
|
+
|
|
11
|
+
### `chainPromise<T>(given: Promise<T> | T): PromiseChain<T>`
|
|
12
|
+
|
|
13
|
+
Transforms a promise or value into a chainable object that automatically handles promise resolution and method forwarding.
|
|
14
|
+
|
|
15
|
+
**Parameters:**
|
|
16
|
+
- `given`: A promise or any value to make chainable
|
|
17
|
+
|
|
18
|
+
**Returns:** A chainable object that maintains the original promise methods (`then`, `catch`, `finally`) while allowing direct method access
|
|
19
|
+
|
|
20
|
+
**Example:**
|
|
21
|
+
```typescript
|
|
22
|
+
import { chainPromise } from './promiseChain'
|
|
23
|
+
|
|
24
|
+
// Basic usage
|
|
25
|
+
const result = await chainPromise(Promise.resolve({ name: 'John', age: 30 })).getName()
|
|
26
|
+
console.log(result) // 'John'
|
|
27
|
+
|
|
28
|
+
// Chaining multiple methods
|
|
29
|
+
const info = await chainPromise(fetchUserData())
|
|
30
|
+
.getProfile()
|
|
31
|
+
.getSettings()
|
|
32
|
+
.getPreferences()
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Type Definitions
|
|
36
|
+
|
|
37
|
+
### `PromiseChain<T>`
|
|
38
|
+
|
|
39
|
+
A type that represents a chainable promise with the following characteristics:
|
|
40
|
+
|
|
41
|
+
- **For Functions**: Returns a chainable function that can be called and returns a `PromiseChain`
|
|
42
|
+
- **For Objects**: Returns a chainable object where all properties return `PromiseChain` instances
|
|
43
|
+
- **For Primitives**: Returns a promise that resolves to the primitive value
|
|
44
|
+
- **Promise Methods**: Maintains original `then`, `catch`, and `finally` methods
|
|
45
|
+
|
|
46
|
+
### `Resolved<T>`
|
|
47
|
+
|
|
48
|
+
A utility type that recursively resolves promise types:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
type Resolved<T> = T extends Promise<infer U>
|
|
52
|
+
? Resolved<U>
|
|
53
|
+
: T extends (...args: infer Args) => infer R
|
|
54
|
+
? (...args: Args) => Resolved<R>
|
|
55
|
+
: T extends object
|
|
56
|
+
? { [k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : Resolved<T[k]> }
|
|
57
|
+
: T
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Usage Examples
|
|
61
|
+
|
|
62
|
+
### Basic Method Chaining
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { chainPromise } from './promiseChain'
|
|
66
|
+
|
|
67
|
+
// Define an API object
|
|
68
|
+
const api = {
|
|
69
|
+
getUser: (id: string) => Promise.resolve({
|
|
70
|
+
id,
|
|
71
|
+
name: 'John Doe',
|
|
72
|
+
email: 'john@example.com',
|
|
73
|
+
getProfile: () => Promise.resolve({
|
|
74
|
+
bio: 'Software developer',
|
|
75
|
+
avatar: 'avatar.jpg',
|
|
76
|
+
getSettings: () => Promise.resolve({
|
|
77
|
+
theme: 'dark',
|
|
78
|
+
notifications: true
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Chain method calls without await
|
|
85
|
+
const settings = await chainPromise(api.getUser('123'))
|
|
86
|
+
.getProfile()
|
|
87
|
+
.getSettings()
|
|
88
|
+
|
|
89
|
+
console.log(settings) // { theme: 'dark', notifications: true }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Function Chaining
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
const mathOperations = {
|
|
96
|
+
add: (a: number) => (b: number) => Promise.resolve(a + b),
|
|
97
|
+
multiply: (a: number) => (b: number) => Promise.resolve(a * b),
|
|
98
|
+
square: (a: number) => Promise.resolve(a * a)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Chain function calls
|
|
102
|
+
const result = await chainPromise(mathOperations.add(5)(10))
|
|
103
|
+
.multiply(2)
|
|
104
|
+
.square()
|
|
105
|
+
|
|
106
|
+
console.log(result) // 900 (15 * 2 = 30, 30^2 = 900)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### API Data Processing
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const dataService = {
|
|
113
|
+
fetchUsers: () => Promise.resolve([
|
|
114
|
+
{ id: 1, name: 'Alice', active: true },
|
|
115
|
+
{ id: 2, name: 'Bob', active: false },
|
|
116
|
+
{ id: 3, name: 'Charlie', active: true }
|
|
117
|
+
]),
|
|
118
|
+
filterActive: (users: any[]) => users.filter(user => user.active),
|
|
119
|
+
mapNames: (users: any[]) => users.map(user => user.name),
|
|
120
|
+
sort: (names: string[]) => names.sort()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Process data through a chain
|
|
124
|
+
const activeUserNames = await chainPromise(dataService.fetchUsers())
|
|
125
|
+
.filterActive()
|
|
126
|
+
.mapNames()
|
|
127
|
+
.sort()
|
|
128
|
+
|
|
129
|
+
console.log(activeUserNames) // ['Alice', 'Charlie']
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Error Handling
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const riskyOperation = () => Promise.resolve({
|
|
136
|
+
mightFail: () => Promise.reject(new Error('Something went wrong')),
|
|
137
|
+
safeOperation: () => Promise.resolve('Success')
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
// Handle errors in the chain
|
|
141
|
+
try {
|
|
142
|
+
const result = await chainPromise(riskyOperation())
|
|
143
|
+
.mightFail()
|
|
144
|
+
.safeOperation()
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('Chain failed:', error.message)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Or use promise methods
|
|
150
|
+
const result = await chainPromise(riskyOperation())
|
|
151
|
+
.mightFail()
|
|
152
|
+
.catch(() => ({ safeOperation: () => Promise.resolve('Fallback') }))
|
|
153
|
+
.safeOperation()
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Mixed Promise and Non-Promise Operations
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const mixedOperations = {
|
|
160
|
+
getData: () => Promise.resolve({ value: 42 }),
|
|
161
|
+
process: (data: any) => data.value * 2, // Synchronous
|
|
162
|
+
validate: (value: number) => Promise.resolve(value > 0),
|
|
163
|
+
format: (isValid: boolean) => isValid ? 'Valid' : 'Invalid'
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Chain synchronous and asynchronous operations
|
|
167
|
+
const result = await chainPromise(mixedOperations.getData())
|
|
168
|
+
.process() // Synchronous
|
|
169
|
+
.validate() // Asynchronous
|
|
170
|
+
.format() // Asynchronous
|
|
171
|
+
|
|
172
|
+
console.log(result) // 'Valid'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Working with Arrays
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const arrayOperations = {
|
|
179
|
+
getNumbers: () => Promise.resolve([1, 2, 3, 4, 5]),
|
|
180
|
+
filter: (arr: number[]) => arr.filter(n => n % 2 === 0),
|
|
181
|
+
map: (arr: number[]) => arr.map(n => n * 2),
|
|
182
|
+
reduce: (arr: number[]) => arr.reduce((sum, n) => sum + n, 0)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Chain array operations
|
|
186
|
+
const sum = await chainPromise(arrayOperations.getNumbers())
|
|
187
|
+
.filter() // [2, 4]
|
|
188
|
+
.map() // [4, 8]
|
|
189
|
+
.reduce() // 12
|
|
190
|
+
|
|
191
|
+
console.log(sum) // 12
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Key Features
|
|
195
|
+
|
|
196
|
+
- **Automatic Promise Resolution**: No need to use `await` at every step
|
|
197
|
+
- **Method Forwarding**: Direct access to methods on promise results
|
|
198
|
+
- **Type Safety**: Full TypeScript support with proper type inference
|
|
199
|
+
- **Promise Method Preservation**: Maintains `then`, `catch`, and `finally` methods
|
|
200
|
+
- **Caching**: WeakMap-based caching prevents duplicate wrapping
|
|
201
|
+
- **Flexible**: Works with functions, objects, and primitive values
|
|
202
|
+
- **Error Propagation**: Errors in the chain are properly propagated
|
|
203
|
+
|
|
204
|
+
## Use Cases
|
|
205
|
+
|
|
206
|
+
- **API Chaining**: Chain multiple API calls without intermediate awaits
|
|
207
|
+
- **Data Processing Pipelines**: Process data through multiple transformation steps
|
|
208
|
+
- **Functional Programming**: Create fluent interfaces for promise-based operations
|
|
209
|
+
- **Reducing Boilerplate**: Eliminate repetitive `await` statements
|
|
210
|
+
- **Complex Async Workflows**: Simplify complex asynchronous operation chains
|
|
211
|
+
- **Promise Composition**: Compose multiple promise-based operations elegantly
|
|
212
|
+
|
|
213
|
+
## Performance Considerations
|
|
214
|
+
|
|
215
|
+
- **Caching**: The system uses WeakMaps to cache wrapped objects, preventing duplicate wrapping
|
|
216
|
+
- **Lazy Evaluation**: Methods are only called when the chain is awaited
|
|
217
|
+
- **Memory Management**: WeakMaps ensure proper garbage collection of cached objects
|
|
218
|
+
- **Proxy Overhead**: Each chainable object is wrapped in a Proxy, which has minimal performance impact for most use cases
|