promise-logic 2.4.4 → 2.4.6

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 (2) hide show
  1. package/README.md +122 -191
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,227 +1,158 @@
1
- # Promise Logic - A Declarative Promise Library Based on Logic Gates
2
1
 
3
- This description might sound a bit awkward, but it essentially means a Promise wrapper library designed based on the concept of logic gates, providing a more declarative syntax. However, promiseLogic's implementation is based on promises, so we can say it's a promise-based wrapper library.
4
2
 
5
- This design is really interesting. I spent a lot of time thinking about it and realized that promise state machines ultimately have only two outcomes: either fulfilled or rejected. This state design can be abstracted using boolean operations, allowing for declarative writing that reduces our memory burden and mental load during development. Let's look at some examples.
6
3
 
7
- Installation:
4
+ ### **1. Core Philosophy**
8
5
 
9
- npm:
6
+ **Replace API Memory with Logical Concepts**
7
+ The design philosophy of `promise-logic` is: **Developers should focus on business logic, not the details of Promise APIs**.
8
+ Traditional Promise combinations (such as `Promise.all`, `Promise.race`) have naming and semantics that are not intuitive enough, especially in complex asynchronous scenarios where code readability rapidly declines.
9
+ `promise-logic` abstracts asynchronous combinations into logical operations like `and`, `or`, `xor` through the concept of **Logic Gates**, making code semantically clear and self-explanatory.
10
10
 
11
- ```bash
12
- npm install promise-logic
13
- ```
14
-
15
- ```javascript
16
- import PromiseLogic from 'promise-logic';
17
-
18
- // Native Promise
19
- const promise = Promise.all([
20
- Promise.resolve(1),
21
- Promise.resolve(2),
22
- Promise.resolve(3)
23
- ]);
24
-
25
- // Promise Logic -- AND gate
26
- const promiseLogic = PromiseLogic.and([
27
- Promise.resolve(1),
28
- Promise.resolve(2),
29
- Promise.resolve(3)
30
- ]); // [1,2,3]
31
-
32
- // This syntax is more semantic, easier to understand, reduces team communication costs, and is more friendly to learners
33
-
34
- // Native promise
35
- const promise = Promise.any([
36
- Promise.resolve(1),
37
- Promise.reject(2),
38
- Promise.resolve(3)
39
- ]); // 1
40
-
41
- // Promise Logic -- OR gate
42
- const promiseLogicOr = PromiseLogic.or([
43
- Promise.resolve(1),
44
- Promise.reject(2),
45
- Promise.resolve(3)
46
- ]); // 1
47
-
48
- // The result of or is consistent with native promise.any, but from here, I think you should see the pattern, and there's more to it
49
- ```
50
-
51
- It also supports TypeScript syntax:
52
-
53
- ```javascript
54
- const promiseLogic =
55
- PromiseLogic.and <
56
- number >
57
- [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]; // [1,2,3]
58
-
59
- const promiseLogicOr =
60
- PromiseLogic.or <
61
- string >
62
- [
63
- Promise.resolve('data 1'),
64
- Promise.reject('error 2'),
65
- Promise.resolve('data 3')
66
- ]; // 'data 1'
67
- ```
68
-
69
- #### We can also create flexible combinations for complex request resources
70
-
71
- ```javascript
72
- // OR + AND
73
- // Suppose we have a scenario where we want to get data from multiple data sources, need the fastest request result, but also need all requests in one request group to succeed before returning a result. Implementing this with native Promise would be extremely complex
74
-
75
- // Now we can implement it like this:
76
- const result = await PromiseLogic.or([
77
- PromiseLogic.and([
78
- // Request group 1
79
- fetch('/api/data1'), // Request 1
80
- fetch('/api/data2') // Request 2
81
- ]),
82
- PromiseLogic.and([
83
- // Request group 2
84
- fetch('/api/data3'), // Request 3
85
- fetch('/api/data4') // Request 4
86
- ])
87
- ]); // Result: [fetch('/api/data1'),fetch('/api/data2')] or [fetch('/api/data3'),fetch('/api/data4')] or error
88
-
89
- // This returns the fastest successful result, and this successful result must come from a request group where all requests in the AND combination have succeeded
90
- ```
91
-
92
- Of course, there are other logic gates like exclusive OR, NAND, NOR, XNOR, majority, etc. Their implementations are all very simple, so I won't introduce them one by one. They all use the same pattern but have different logical semantics, so you can choose which one to use based on your scenario.
11
+ ---
93
12
 
94
- #### `PromiseLogic.xor`
13
+ ### **2. Features**
95
14
 
96
- #### `PromiseLogic.majority`
15
+ 1. **Logical Semantics**
16
+ - `and`: All tasks must succeed (equivalent to `Promise.all`)
17
+ - `or`: At least one task succeeds (equivalent to `Promise.race`)
18
+ - `xor`: **Exactly one task succeeds** (no direct equivalent in traditional Promise)
19
+ - `nand`: All tasks fail
97
20
 
98
- #### `PromiseLogic.nor`
21
+ - `not`: Inverts the result of a single Promise
22
+ - `majority`: Most tasks succeed
99
23
 
100
- #### `PromiseLogic.xnor`
24
+ 2. **Zero Dependencies**
25
+ Only depends on native Promise, no additional runtime dependencies.
101
26
 
102
- #### `PromiseLogic.nand`
27
+ 3. **Full Test Coverage**
28
+ All logic gates have undergone rigorous unit testing to ensure behavior meets expectations.
103
29
 
104
- #### `PromiseLogic.not`
30
+ 4. **Clear Error Classification**
31
+ - `PromiseLogicError` unified error type
32
+ - `error.type` distinguishes specific logical errors (e.g., `'XOR_ERROR'`)
105
33
 
106
- We've kept the native methods for more straightforward usage:
34
+ ---
107
35
 
108
- - `PromiseLogic.allSettled`
109
- - `PromiseLogic.race`
36
+ ### **3. Installation**
110
37
 
111
- ### `PromiseLogic.createFlipFlop` - Async Boolean Flip-Flop
38
+ ```bash
39
+ npm install promise-logic
40
+ ```
112
41
 
113
- This is used to create a stateful flip-flop for managing boolean states in asynchronous operations. You might be wondering why, but let's continue:
42
+ ---
114
43
 
115
- Here's how to use this flip-flop to manage connection states:
44
+ ### **4. Quick Start**
116
45
 
46
+ #### Example: Primary/Backup Service Call (XOR Scenario)
117
47
  ```javascript
118
- const connectionState = PromiseLogic.createFlipFlop(false);
119
-
120
- // Managing device connection state
121
- class ConnectionManager {
122
- constructor() {
123
- this.connectionState = PromiseLogic.createFlipFlop(false); // Initial disconnected state
124
- }
125
-
126
- async connect() {
127
- console.log('Connecting...');
128
- // Simulate connection process
129
- await new Promise((resolve) => setTimeout(resolve, 1000));
130
- await this.connectionState.set(true); // Set connected state
131
- console.log('Connected!');
132
- }
133
-
134
- async disconnect() {
135
- console.log('Disconnecting...');
136
- await this.connectionState.set(false); // Set disconnected state
137
- console.log('Disconnected!');
138
- }
139
-
140
- async waitForConnection() {
141
- console.log('Waiting for connection...');
142
- await this.connectionState.waitFor(true); // Wait until connected
143
- console.log('Connection established!');
144
- }
145
-
146
- async monitorConnection() {
147
- // Monitor state changes
148
- while (true) {
149
- const newState = await this.connectionState.waitForChange();
150
- console.log('Connection state changed to:', newState ? 'connected' : 'disconnected');
151
- if (!newState) break; // Exit if disconnected
152
- }
153
- }
154
- }
48
+ import PromiseLogic from 'promise-logic';
155
49
 
156
- // Usage
157
- const manager = new ConnectionManager();
50
+ // Primary service call
51
+ const primary = fetch('https://api.main.com/data');
52
+ // Backup service call
53
+ const backup = fetch('https://api.backup.com/data');
54
+
55
+ // Execute XOR logic: exactly one success
56
+ PromiseLogic.xor([primary, backup])
57
+ .then(result => {
58
+ console.log('Successfully fetched data:', result);
59
+ })
60
+ .catch(error => {
61
+ if (error.type === 'XOR_ERROR') {
62
+ console.error('Both primary and backup services succeeded or failed, which does not meet XOR semantics');
63
+ } else {
64
+ console.error('Network error:', error);
65
+ }
66
+ });
67
+ ```
158
68
 
159
- // Start monitoring in background
160
- manager.monitorConnection();
69
+ #### Example: Majority Decision (Majority Scenario)
70
+ ```javascript
71
+ import PromiseLogic from 'promise-logic';
161
72
 
162
- // Connect and wait
163
- await manager.connect();
164
- await manager.waitForConnection();
73
+ const services = [
74
+ fetch('https://api.node1.com/vote'),
75
+ fetch('https://api.node2.com/vote'),
76
+ fetch('https://api.node3.com/vote')
77
+ ];
78
+
79
+ PromiseLogic.majority(services)
80
+ .then(results => {
81
+ console.log('Majority of services returned success:', results);
82
+ })
83
+ .catch(error => {
84
+ console.error('Majority of services failed:', error);
85
+ });
86
+ ```
165
87
 
166
- // Disconnect after 2 seconds
167
- setTimeout(async () => {
168
- await manager.disconnect();
169
- }, 2000);
88
+ ```typescript
89
+ import PromiseLogic from 'promise-logic/typescript';
90
+
91
+ const services = [
92
+ fetch('https://api.node1.com/vote'),
93
+ fetch('https://api.node2.com/vote'),
94
+ fetch('https://api.node3.com/vote')
95
+ ];
96
+
97
+ PromiseLogic.majority<Response>(services)
98
+ .then(results => {
99
+ console.log('Majority of services returned success:', results);
100
+ })
101
+ .catch(error => {
102
+ console.error('Majority of services failed:', error);
103
+ });
170
104
  ```
171
105
 
172
- This is because in asynchronous operations, we often need to make decisions and execute subsequent operations based on a certain state, and this flip-flop can help us manage this state in asynchronous operations.
106
+ ---
173
107
 
174
- API
108
+ ### **5. API Reference**
175
109
 
176
- ```javascript
177
- PromiseLogic.createFlipFlop(initialState);
178
- ```
110
+ | API | Description |
111
+ | :--------- | :-------------------------------------------------------------------------- |
112
+ | `and` | All Promises succeed, returns result array; any failure causes overall failure. |
113
+ | `or` | At least one Promise succeeds, returns first success result; all failures cause overall failure. |
114
+ | `xor` | **Exactly one Promise succeeds**, returns that result; otherwise throws `XOR_ERROR`. |
115
+ | `nand` | All Promises fail, returns error array; any success causes overall failure. |
116
+ | `not` | Inverts the result of a single Promise |
117
+ | `majority` | More than half of Promises succeed, returns success result array; otherwise overall failure. |
179
118
 
180
- **Parameters:**
119
+ ---
181
120
 
182
- - `initialState` (boolean, optional): Initial state, default value is `false`
121
+ ### **6. Real-world Application Scenarios**
183
122
 
184
- **Returns:**
185
- An object with the following methods:
123
+ 1. **Primary/Backup Service Calls**
124
+ - Use `xor` to ensure **exactly one service responds**, avoiding duplicate processing.
125
+ 2. **Distributed Decision Making**
126
+ - Use `majority` to implement majority consensus (e.g., distributed voting).
127
+ 3. **Resource Competition**
128
+ - Use `or` to get the first available resource (e.g., CDN node selection).
129
+ - Use `not` to check if a resource is available.
130
+ 4. **Full-link Validation**
131
+ - Use `and` to ensure all dependent services succeed (e.g., order creation).
186
132
 
187
- - `getState()`: Returns the current boolean state
188
- - `set(newState: boolean)`: Sets the new state and returns Promise<boolean>
189
- - `toggle()`: Toggles the current state and returns Promise<boolean>
190
- - `waitForChange()`: Returns a Promise that resolves when the state changes
191
- - `waitFor(targetState: boolean)`: Returns a Promise that resolves when the state matches the target
133
+ ---
192
134
 
193
- ### `createPromiseLogic(options)`
135
+ ### **7. Contribution Guide**
194
136
 
195
- Creates a customizable object containing PromiseLogic methods with configurable naming.
137
+ 1. **Development Environment**
138
+ ```bash
139
+ git clone https://github.com/haowhite/promise-logic.git
140
+ cd promise-logic
141
+ npm install
142
+ ```
143
+ 2. **Testing**
144
+ ```bash
145
+ npm test
146
+ ```
147
+ 3. **Commit Guidelines**
148
+ - Commit messages must include prefixes like `feat:` (new feature), `fix:` (bug fix), `docs:` (documentation).
149
+ - Pull Requests must include test cases.
196
150
 
197
- **Parameters:**
151
+ ---
198
152
 
199
- - `options` (object, optional): Configuration options
200
- - `prefix` (string, optional): String to prepend to all method names
201
- - `suffix` (string, optional): String to append to all method names
202
- - `rename` (Record<string, string>, optional): Mapping of original method names to new names
153
+ ### **8. Resource Links**
203
154
 
204
- **Returns:**
205
- An object containing PromiseLogic methods with customized names.
155
+ - **GitHub Repository**:[https://github.com/xier123456/promise-logic](https://github.com/xier123456/promise-logic)
156
+ - **npm Package**:[https://www.npmjs.com/package/promise-logic](https://www.npmjs.com/package/promise-logic)
157
+ - **Issue Tracking**:[GitHub Issues](https://github.com/xier123456/promise-logic/issues)
206
158
 
207
- ```javascript
208
- // Basic usage - returns all methods with default names
209
- const logic = createPromiseLogic();
210
-
211
- // Combined options
212
- const combined = createPromiseLogic({
213
- prefix: 'async', // Add prefix
214
- suffix: 'Op', // Add suffix
215
- rename: {
216
- // API renaming
217
- and: 'Conjunction',
218
- or: 'Disjunction'
219
- }
220
- });
221
-
222
- // Call combined method (async)+ (Conjunction) + (Op)
223
- const result = await logic.asycnConjunctionOp([
224
- fetch('/api/data1'),
225
- fetch('/api/data2')
226
- ]);
227
- ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promise-logic",
3
- "version": "2.4.4",
3
+ "version": "2.4.6",
4
4
  "description": "Compose promises with logic gate semantics (AND, OR, XOR, NAND, NOR, XNOR, Majority). Forget APIs, remember logic.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",