promise-logic 2.4.4 → 2.4.5

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 +103 -194
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,227 +1,136 @@
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
- ```
11
+ ---
91
12
 
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.
13
+ ### **2. Features**
93
14
 
94
- #### `PromiseLogic.xor`
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
20
+ - `Majority`: Most tasks succeed
95
21
 
96
- #### `PromiseLogic.majority`
22
+ 2. **Zero Dependencies**
23
+ Only depends on native Promise, no additional runtime dependencies.
97
24
 
98
- #### `PromiseLogic.nor`
25
+ 3. **Full Test Coverage**
26
+ All logic gates have undergone rigorous unit testing to ensure behavior meets expectations.
99
27
 
100
- #### `PromiseLogic.xnor`
28
+ 4. **Clear Error Classification**
29
+ - `PromiseLogicError` unified error type
30
+ - `error.type` distinguishes specific logical errors (e.g., `'XOR_ERROR'`)
101
31
 
102
- #### `PromiseLogic.nand`
32
+ ---
103
33
 
104
- #### `PromiseLogic.not`
34
+ ### **3. Installation**
105
35
 
106
- We've kept the native methods for more straightforward usage:
107
-
108
- - `PromiseLogic.allSettled`
109
- - `PromiseLogic.race`
110
-
111
- ### `PromiseLogic.createFlipFlop` - Async Boolean Flip-Flop
36
+ ```bash
37
+ npm install promise-logic
38
+ ```
112
39
 
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:
40
+ ---
114
41
 
115
- Here's how to use this flip-flop to manage connection states:
42
+ ### **4. Quick Start**
116
43
 
44
+ #### Example: Primary/Backup Service Call (XOR Scenario)
117
45
  ```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
46
+ import { XOR } from 'promise-logic';
47
+
48
+ // Primary service call
49
+ const primary = fetch('https://api.main.com/data');
50
+ // Backup service call
51
+ const backup = fetch('https://api.backup.com/data');
52
+
53
+ // Execute XOR logic: exactly one success
54
+ XOR(primary, backup)
55
+ .then(result => {
56
+ console.log('Successfully fetched data:', result);
57
+ })
58
+ .catch(error => {
59
+ if (error.type === 'XOR_ERROR') {
60
+ console.error('Both primary and backup services succeeded or failed, which does not meet XOR semantics');
61
+ } else {
62
+ console.error('Network error:', error);
152
63
  }
153
- }
154
- }
155
-
156
- // Usage
157
- const manager = new ConnectionManager();
158
-
159
- // Start monitoring in background
160
- manager.monitorConnection();
161
-
162
- // Connect and wait
163
- await manager.connect();
164
- await manager.waitForConnection();
64
+ });
65
+ ```
165
66
 
166
- // Disconnect after 2 seconds
167
- setTimeout(async () => {
168
- await manager.disconnect();
169
- }, 2000);
67
+ #### Example: Majority Decision (Majority Scenario)
68
+ ```javascript
69
+ import { Majority } from 'promise-logic';
70
+
71
+ const services = [
72
+ fetch('https://api.node1.com/vote'),
73
+ fetch('https://api.node2.com/vote'),
74
+ fetch('https://api.node3.com/vote')
75
+ ];
76
+
77
+ Majority(...services)
78
+ .then(results => {
79
+ console.log('Majority of services returned success:', results);
80
+ })
81
+ .catch(error => {
82
+ console.error('Majority of services failed:', error);
83
+ });
170
84
  ```
171
85
 
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.
86
+ ---
173
87
 
174
- API
88
+ ### **5. API Reference**
175
89
 
176
- ```javascript
177
- PromiseLogic.createFlipFlop(initialState);
178
- ```
90
+ | API | Description |
91
+ | :--------- | :-------------------------------------------------------------------------- |
92
+ | `AND` | All Promises succeed, returns result array; any failure causes overall failure. |
93
+ | `OR` | At least one Promise succeeds, returns first success result; all failures cause overall failure. |
94
+ | `XOR` | **Exactly one Promise succeeds**, returns that result; otherwise throws `XOR_ERROR`. |
95
+ | `NAND` | All Promises fail, returns error array; any success causes overall failure. |
96
+ | `Majority` | More than half of Promises succeed, returns success result array; otherwise overall failure. |
179
97
 
180
- **Parameters:**
98
+ ---
181
99
 
182
- - `initialState` (boolean, optional): Initial state, default value is `false`
100
+ ### **6. Real-world Application Scenarios**
183
101
 
184
- **Returns:**
185
- An object with the following methods:
102
+ 1. **Primary/Backup Service Calls**
103
+ - Use `XOR` to ensure **exactly one service responds**, avoiding duplicate processing.
104
+ 2. **Distributed Decision Making**
105
+ - Use `Majority` to implement majority consensus (e.g., distributed voting).
106
+ 3. **Resource Competition**
107
+ - Use `OR` to get the first available resource (e.g., CDN node selection).
108
+ 4. **Full-link Validation**
109
+ - Use `AND` to ensure all dependent services succeed (e.g., order creation).
186
110
 
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
111
+ ---
192
112
 
193
- ### `createPromiseLogic(options)`
113
+ ### **7. Contribution Guide**
194
114
 
195
- Creates a customizable object containing PromiseLogic methods with configurable naming.
115
+ 1. **Development Environment**
116
+ ```bash
117
+ git clone https://github.com/haowhite/promise-logic.git
118
+ cd promise-logic
119
+ npm install
120
+ ```
121
+ 2. **Testing**
122
+ ```bash
123
+ npm test
124
+ ```
125
+ 3. **Commit Guidelines**
126
+ - Commit messages must include prefixes like `feat:` (new feature), `fix:` (bug fix), `docs:` (documentation).
127
+ - Pull Requests must include test cases.
196
128
 
197
- **Parameters:**
129
+ ---
198
130
 
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
131
+ ### **8. Resource Links**
203
132
 
204
- **Returns:**
205
- An object containing PromiseLogic methods with customized names.
133
+ - **GitHub Repository**:[https://github.com/xier123456/promise-logic](https://github.com/xier123456/promise-logic)
134
+ - **npm Package**:[https://www.npmjs.com/package/promise-logic](https://www.npmjs.com/package/promise-logic)
135
+ - **Issue Tracking**:[GitHub Issues](https://github.com/xier123456/promise-logic/issues)
206
136
 
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.5",
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",