defered-branch 1.2.1 β 2.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 +174 -64
- package/dist/index.d.ts +72 -16
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,111 +1,221 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
A tiny TypeScript/JavaScript utility for deferred branching logic.
|
|
4
|
-
It provides a small, chainable API to register conditional branches and two kinds of "no-match" handlers: one that runs immediately when no branch was matched, and another that runs later when you call `run()`.
|
|
1
|
+
# Defered Branch πΏ
|
|
5
2
|
|
|
6
3
|
For more awesome packages, check out [my homepageπ](https://baendlorel.github.io/?repoType=npm)
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
> Sometimes we need to judge something with multiple cases, but the main job should be done later. So we have Defered Branch! β¨
|
|
6
|
+
|
|
7
|
+
A TypeScript/JavaScript library that provides elegant deferred conditional branching with two powerful variants: **defered-branch** for immediate execution and **defered-branch-dynamic** for reusable logic patterns.
|
|
8
|
+
|
|
9
|
+
## π Features
|
|
9
10
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
11
|
+
- π― **Two Execution Models**: Choose between immediate execution or dynamic reusable logic
|
|
12
|
+
- π **Type Safe**: Full TypeScript support with proper type inference
|
|
13
|
+
- πͺΆ **Lightweight**: Zero dependencies, minimal footprint
|
|
14
|
+
- π§© **Flexible**: Works with any function signature and return types
|
|
15
|
+
- π¦ **ESM Ready**: Modern module system support
|
|
15
16
|
|
|
16
|
-
## Installation
|
|
17
|
+
## π¦ Installation
|
|
17
18
|
|
|
18
19
|
```bash
|
|
19
|
-
pnpm add defered-branch
|
|
20
|
-
# or
|
|
21
20
|
npm install defered-branch
|
|
21
|
+
# or
|
|
22
|
+
pnpm add defered-branch
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
##
|
|
25
|
+
## π When to Use Which?
|
|
26
|
+
|
|
27
|
+
### `deferedBranch` - One-time Immediate Execution πββοΈ
|
|
28
|
+
|
|
29
|
+
Perfect for scenarios where you need to evaluate conditions **once** and execute immediately:
|
|
30
|
+
|
|
31
|
+
- One-time conditional flows
|
|
32
|
+
- Static condition evaluation
|
|
33
|
+
|
|
34
|
+
### `deferedBranchDynamic` - Reusable Logic Patterns π
|
|
35
|
+
|
|
36
|
+
Ideal when you need to **reuse** the same branching logic multiple times with different inputs:
|
|
25
37
|
|
|
26
|
-
|
|
38
|
+
- Event handlers with varying states
|
|
39
|
+
- Repeated conditional logic with dynamic data
|
|
40
|
+
- State-dependent operations that change over time
|
|
27
41
|
|
|
28
|
-
|
|
42
|
+
## π Usage Examples
|
|
43
|
+
|
|
44
|
+
### Basic deferedBranch Usage
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
29
47
|
import { deferedBranch } from 'defered-branch';
|
|
48
|
+
|
|
49
|
+
// Steps to use:
|
|
50
|
+
// 1. Create instance
|
|
51
|
+
const branch = deferedBranch();
|
|
52
|
+
|
|
53
|
+
// 2. Add conditional branches
|
|
54
|
+
branch
|
|
55
|
+
.add(user.role === 'admin', () => 'Access granted to admin panel')
|
|
56
|
+
.add(user.role === 'user', () => 'Access granted to user dashboard')
|
|
57
|
+
.add(user.role === 'guest', () => 'Limited access granted');
|
|
58
|
+
|
|
59
|
+
// 3. Handle no-match case (optional)
|
|
60
|
+
branch.nomatch(() => 'Access denied');
|
|
61
|
+
|
|
62
|
+
// 4. Execute and get result
|
|
63
|
+
const result = branch.run();
|
|
64
|
+
console.log(result); // Output based on user.role
|
|
30
65
|
```
|
|
31
66
|
|
|
32
|
-
|
|
67
|
+
### Advanced deferedBranch with Parameters
|
|
33
68
|
|
|
34
|
-
```
|
|
35
|
-
|
|
69
|
+
```typescript
|
|
70
|
+
const calculator = deferedBranch<(a: number, b: number) => number>();
|
|
71
|
+
|
|
72
|
+
calculator
|
|
73
|
+
.add(operation === 'add', (a, b) => a + b)
|
|
74
|
+
.add(operation === 'multiply', (a, b) => a * b)
|
|
75
|
+
.add(operation === 'divide', (a, b) => a / b)
|
|
76
|
+
.nomatch(() => {
|
|
77
|
+
throw new Error('Unknown operation');
|
|
78
|
+
});
|
|
36
79
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.add(false, () => 'A')
|
|
40
|
-
.add(true, () => 'B');
|
|
80
|
+
const result = calculator.run(10, 5); // Returns calculated result
|
|
81
|
+
```
|
|
41
82
|
|
|
42
|
-
|
|
83
|
+
### deferedBranchDynamic for Reusable Logic
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { deferedBranchDynamic } from 'defered-branch';
|
|
87
|
+
|
|
88
|
+
// Steps to use:
|
|
89
|
+
// 1. Create instance
|
|
90
|
+
const statusHandler = deferedBranchDynamic<(message: string) => void>();
|
|
91
|
+
|
|
92
|
+
// 2. Add predicate-based branches
|
|
93
|
+
statusHandler
|
|
94
|
+
.add(
|
|
95
|
+
() => server.status === 'online',
|
|
96
|
+
(msg) => logger.info(`β
${msg}`)
|
|
97
|
+
)
|
|
98
|
+
.add(
|
|
99
|
+
() => server.status === 'maintenance',
|
|
100
|
+
(msg) => logger.warn(`β οΈ ${msg}`)
|
|
101
|
+
)
|
|
102
|
+
.add(
|
|
103
|
+
() => server.status === 'offline',
|
|
104
|
+
(msg) => logger.error(`β ${msg}`)
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// 3. Add fallback handler
|
|
108
|
+
statusHandler.nomatch((msg) => logger.debug(`π€ Unknown status: ${msg}`));
|
|
109
|
+
|
|
110
|
+
// 4. Use repeatedly with different conditions
|
|
111
|
+
statusHandler.predicate(); // Evaluates current server.status
|
|
112
|
+
statusHandler.run('Server health check completed');
|
|
113
|
+
|
|
114
|
+
// Later, when server.status changes...
|
|
115
|
+
statusHandler.predicate(); // Re-evaluates with new status
|
|
116
|
+
statusHandler.run('Status updated');
|
|
43
117
|
```
|
|
44
118
|
|
|
45
|
-
|
|
119
|
+
### Real-world Example: Theme Switching
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const themeHandler = deferedBranchDynamic<() => void>();
|
|
123
|
+
|
|
124
|
+
themeHandler
|
|
125
|
+
.add(
|
|
126
|
+
() => preferences.theme === 'dark',
|
|
127
|
+
() => applyDarkTheme()
|
|
128
|
+
)
|
|
129
|
+
.add(
|
|
130
|
+
() => preferences.theme === 'light',
|
|
131
|
+
() => applyLightTheme()
|
|
132
|
+
)
|
|
133
|
+
.add(
|
|
134
|
+
() => preferences.theme === 'auto',
|
|
135
|
+
() => applySystemTheme()
|
|
136
|
+
)
|
|
137
|
+
.nomatch(() => {
|
|
138
|
+
// usually handles parameter validations
|
|
139
|
+
throw new TypeError('Invalid theme preference');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Reuse whenever preferences change
|
|
143
|
+
function onConfigChange() {
|
|
144
|
+
themeHandler.predicate();
|
|
145
|
+
xxxHandler.predicate();
|
|
146
|
+
yyyHandler.predicate();
|
|
147
|
+
|
|
148
|
+
// some other logic...create some objects..
|
|
149
|
+
// some other logic...run some funtions...
|
|
150
|
+
|
|
151
|
+
themeHandler.run();
|
|
152
|
+
xxxHandler.run();
|
|
153
|
+
yyyHandler.run();
|
|
154
|
+
}
|
|
155
|
+
```
|
|
46
156
|
|
|
47
|
-
|
|
157
|
+
## π§ API Reference
|
|
48
158
|
|
|
49
|
-
|
|
50
|
-
- `deferedNomatch(handler: Fn)` β registers a handler that will be executed when `run()` is called and no branch matched.
|
|
159
|
+
### deferedBranch()
|
|
51
160
|
|
|
52
|
-
|
|
161
|
+
Creates a new deferred branch instance for immediate execution scenarios.
|
|
53
162
|
|
|
54
|
-
|
|
55
|
-
import { deferedBranch } from 'defered-branch';
|
|
163
|
+
#### Methods
|
|
56
164
|
|
|
57
|
-
|
|
58
|
-
deferedBranch()
|
|
59
|
-
.add(false, () => 'x')
|
|
60
|
-
.nomatch(() => console.log('immediate nomatch')) // prints now
|
|
61
|
-
.add(true, () => console.log('will not be printed')); // ignored for the already-called nomatch
|
|
165
|
+
##### `.add(condition: boolean, branch: Function): DeferBranch`
|
|
62
166
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
.deferedNomatch(() => 'deferred fallback');
|
|
167
|
+
- Adds a conditional branch that executes if condition is `true`
|
|
168
|
+
- **Overrides** previous matched branches
|
|
169
|
+
- Returns the instance for chaining
|
|
67
170
|
|
|
68
|
-
|
|
69
|
-
```
|
|
171
|
+
##### `.nomatch(handler: Function): DeferBranch`
|
|
70
172
|
|
|
71
|
-
|
|
173
|
+
- Sets an immediate fallback handler
|
|
174
|
+
- **Executes instantly** if no previous branch matched
|
|
175
|
+
- **Ignores** later matched branches
|
|
72
176
|
|
|
73
|
-
|
|
177
|
+
##### `.run(...args): any`
|
|
74
178
|
|
|
75
|
-
|
|
179
|
+
- Executes the matched branch or fallback handler
|
|
180
|
+
- Passes arguments to the executed function
|
|
181
|
+
- Returns the function's return value or `undefined`
|
|
76
182
|
|
|
77
|
-
|
|
183
|
+
### deferedBranchDynamic()
|
|
78
184
|
|
|
79
|
-
|
|
185
|
+
Creates a new dynamic deferred branch instance for reusable logic patterns.
|
|
80
186
|
|
|
81
|
-
|
|
187
|
+
#### Methods
|
|
82
188
|
|
|
83
|
-
|
|
189
|
+
##### `.add(condition: Predicate, branch: Function): DeferBranchDynamic`
|
|
84
190
|
|
|
85
|
-
|
|
191
|
+
- Adds a predicate-based conditional branch
|
|
192
|
+
- `condition` is a function that returns boolean
|
|
193
|
+
- **Overrides** previous matched branches
|
|
86
194
|
|
|
87
|
-
|
|
195
|
+
##### `.nomatch(handler: Function): DeferBranchDynamic`
|
|
88
196
|
|
|
89
|
-
|
|
197
|
+
- Sets a fallback handler for when no predicates match
|
|
198
|
+
- Executes during `.predicate()` evaluation
|
|
90
199
|
|
|
91
|
-
|
|
200
|
+
##### `.predicate(...args): void`
|
|
92
201
|
|
|
93
|
-
|
|
202
|
+
- Evaluates all conditions to find the first match
|
|
203
|
+
- Call this before `.run()` to update the matched branch
|
|
204
|
+
- Essential for dynamic behavior
|
|
94
205
|
|
|
95
|
-
|
|
206
|
+
##### `.run(...args): any`
|
|
96
207
|
|
|
97
|
-
|
|
208
|
+
- Executes the currently matched branch
|
|
209
|
+
- Returns the function's return value or `undefined`
|
|
98
210
|
|
|
99
|
-
##
|
|
211
|
+
## π License
|
|
100
212
|
|
|
101
|
-
|
|
102
|
-
- The package entrypoint is an ESM module at `./dist/index.mjs`.
|
|
213
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
103
214
|
|
|
104
|
-
##
|
|
215
|
+
## π€ Contributing
|
|
105
216
|
|
|
106
|
-
|
|
217
|
+
Contributions are welcome! Please feel free to submit issues and pull requests.
|
|
107
218
|
|
|
108
|
-
|
|
219
|
+
---
|
|
109
220
|
|
|
110
|
-
|
|
111
|
-
- License: MIT
|
|
221
|
+
Made with β€οΈ by [Kasukabe Tsumugi](https://github.com/baendlorel) (´q⒠ᡠβ’q`) β‘
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare class DeferBranch {
|
|
1
|
+
declare class DeferBranch<BranchFn extends AnyFn, NoMatchFn extends AnyFn = AnyFn> {
|
|
2
2
|
private _branch;
|
|
3
3
|
private _nomatch;
|
|
4
4
|
/**
|
|
@@ -8,42 +8,98 @@ declare class DeferBranch {
|
|
|
8
8
|
* @param branch the branch to run when matched
|
|
9
9
|
* @returns this
|
|
10
10
|
*/
|
|
11
|
-
add(condition: boolean, branch:
|
|
11
|
+
add(condition: boolean, branch: BranchFn): DeferBranch<BranchFn>;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* - This will be called **instantly
|
|
13
|
+
* Register a handler to be called when no branch matched
|
|
14
|
+
* - This will be called **instantly and ignores later matched branches**
|
|
15
15
|
* @param handler handle the exhausted case
|
|
16
16
|
* @returns this
|
|
17
17
|
*/
|
|
18
|
-
nomatch(handler:
|
|
18
|
+
nomatch(handler: AnyFn): DeferBranch<BranchFn>;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
* -
|
|
20
|
+
* If some branch matched, return its returnValue
|
|
21
|
+
* - if no branch matched, return the nomatch handler's returnValue
|
|
22
|
+
* - if no branch matched and no nomatch handler, return undefined
|
|
23
|
+
*
|
|
24
|
+
* > Note: Although args are for the matched branch, they will also be passed to nomatch handler
|
|
25
|
+
* @param args arguments to pass to the matched branch or nomatch handler
|
|
26
|
+
*/
|
|
27
|
+
run(...args: Parameters<BranchFn>): ReturnType<BranchFn> | ReturnType<NoMatchFn> | undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
declare class DeferBranchDynamic<BranchFn extends AnyFn, NoMatchFn extends AnyFn = AnyFn> {
|
|
31
|
+
/**
|
|
32
|
+
* & Compress conditions and branches into a single array since they are paired
|
|
33
|
+
*/
|
|
34
|
+
private _condranches;
|
|
35
|
+
private _branch;
|
|
36
|
+
private _nomatch;
|
|
37
|
+
/**
|
|
38
|
+
* Add a new entry
|
|
39
|
+
* - will **override** the previous matched branch
|
|
40
|
+
* @param condition the condition to match
|
|
41
|
+
* @param branch the branch to run when matched
|
|
42
|
+
* @returns this
|
|
43
|
+
*/
|
|
44
|
+
add(condition: Predicate<BranchFn>, branch: BranchFn): DeferBranchDynamic<BranchFn, NoMatchFn>;
|
|
45
|
+
/**
|
|
46
|
+
* When calling `this.predicate` and no branch matched, run this handler
|
|
22
47
|
* @param handler handle the exhausted case
|
|
23
48
|
* @returns this
|
|
24
49
|
*/
|
|
25
|
-
|
|
50
|
+
nomatch(handler: AnyFn): DeferBranchDynamic<BranchFn, NoMatchFn>;
|
|
51
|
+
/**
|
|
52
|
+
* Run the condition to find the first matched branch
|
|
53
|
+
*/
|
|
54
|
+
predicate(...args: Parameters<BranchFn>): void;
|
|
26
55
|
/**
|
|
27
56
|
* If some branch matched, return its returnValue
|
|
28
|
-
*
|
|
29
|
-
* - if no branch matched and no nomatch handler, return undefined
|
|
30
|
-
* @param args arguments to pass to the matched branch or nomatch handler
|
|
57
|
+
* @param args arguments to pass to the matched branch
|
|
31
58
|
*/
|
|
32
|
-
run(...args:
|
|
59
|
+
run(...args: Parameters<BranchFn>): ReturnType<BranchFn> | undefined;
|
|
33
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* ## Steps to use
|
|
64
|
+
* 1. const a = deferedBranch()
|
|
65
|
+
* 2. add branches by a.add(condition, branch)
|
|
66
|
+
* 3. add defered nomatch handler, or add and run at the same time by a.nomatch(handler)
|
|
67
|
+
* 4. run this branch by a.run();
|
|
68
|
+
*
|
|
69
|
+
* ## About
|
|
70
|
+
* @package DeferedBranch
|
|
71
|
+
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
72
|
+
* @version 2.0.0 (Last Update: 2025.09.20 21:23:15.798)
|
|
73
|
+
* @license MIT
|
|
74
|
+
* @link https://github.com/baendlorel/defered-branch
|
|
75
|
+
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
76
|
+
* @description Sometimes we need to judge something with multiple cases, but the main job should be done later. So we have Defered Branch!
|
|
77
|
+
* @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
|
|
78
|
+
*/
|
|
79
|
+
declare const deferedBranch: () => DeferBranch<AnyFn, AnyFn>;
|
|
34
80
|
/**
|
|
81
|
+
* ## Steps to use
|
|
82
|
+
* 1. const a = deferedBranchDynamic()
|
|
83
|
+
* 2. add branches by a.add(condition, branch)
|
|
84
|
+
* 3. add nomatch handler by a.nomatch(handler)
|
|
85
|
+
* 4. call a.predicate(...) to find the matched branch
|
|
86
|
+
* 5. ...run some other logic
|
|
87
|
+
* 6. run this branch by a.run();
|
|
88
|
+
*
|
|
35
89
|
* ## About
|
|
36
90
|
* @package DeferedBranch
|
|
37
91
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
38
|
-
* @version
|
|
92
|
+
* @version 2.0.0 (Last Update: 2025.09.20 21:23:15.798)
|
|
39
93
|
* @license MIT
|
|
40
94
|
* @link https://github.com/baendlorel/defered-branch
|
|
95
|
+
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
41
96
|
* @description Sometimes we need to judge something with multiple cases, but the main job should be done later. So we have Defered Branch!
|
|
42
97
|
* @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
|
|
43
98
|
*/
|
|
44
|
-
declare const
|
|
99
|
+
declare const deferedBranchDynamic: () => DeferBranchDynamic<AnyFn, AnyFn>;
|
|
45
100
|
|
|
46
|
-
export { deferedBranch };
|
|
101
|
+
export { deferedBranch, deferedBranchDynamic };
|
|
47
102
|
|
|
48
103
|
// # from: src/global.d.ts
|
|
49
|
-
type
|
|
104
|
+
type AnyFn = (...args: any[]) => any;
|
|
105
|
+
type Predicate<Fn extends AnyFn> = (...args: Parameters<Fn>) => boolean;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class
|
|
1
|
+
class n{t=null;h=null;add(n,t){if("function"!=typeof t)throw new TypeError("DeferBranch: branch must be a function");return n&&(this.t=t),this}nomatch(n){if("function"!=typeof n)throw new TypeError("DeferBranch: branch must be a function");return this.t||n(),this}run(...n){return this.t?this.t.apply(null,n):this.h?this.h.apply(null,n):void 0}}class t{i=[];t=null;h=null;add(n,t){if("function"!=typeof n)throw new TypeError("DeferBranch: condition must be a function");if("function"!=typeof t)throw new TypeError("DeferBranch: branch must be a function");return this.i.push(n,t),this}nomatch(n){if("function"!=typeof n)throw new TypeError("DeferBranch: handler must be a function");return this.h=n,this}predicate(...n){const t=this.i.length;for(let n=0;n<t;n+=2)if(this.i[n]())return void(this.t=this.i[n+1]);this.h?.apply(this,n)}run(...n){return this.t?.apply(this,n)}}const r=()=>new n,e=()=>new t;export{r as deferedBranch,e as deferedBranchDynamic};
|