class-resolver 1.1.0 → 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 +209 -17
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/interface.d.ts +19 -2
- package/dist/interface.js +1 -0
- package/dist/interface.js.map +1 -0
- package/dist/resolver.d.ts +46 -10
- package/dist/resolver.js +52 -10
- package/dist/resolver.js.map +1 -0
- package/index.js +4 -2
- package/libs/index.ts +2 -0
- package/libs/interface.ts +20 -4
- package/libs/resolver.ts +73 -22
- package/package.json +24 -14
- package/readme-ja.md +301 -0
- package/dist/libs/interface.js +0 -2
- package/dist/libs/resolver.js +0 -29
- package/yarn.lock +0 -3171
package/README.md
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
# Simple Class resolver
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A lightweight TypeScript/JavaScript library for implementing the Chain of Responsibility pattern with class-based resolvers.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Simple and intuitive API for handling different types of requests
|
|
8
|
+
- Type-safe implementation with TypeScript support
|
|
9
|
+
- Flexible resolver registration (constructor, setUpdaters, addUpdater)
|
|
10
|
+
- Support for multiple resolvers with different handling logic
|
|
11
|
+
- Clear error handling for unsupported types
|
|
12
|
+
- Generic type support for better type safety
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
```bash
|
|
17
|
+
npm install class-resolver
|
|
18
|
+
# or
|
|
19
|
+
yarn add class-resolver
|
|
10
20
|
```
|
|
21
|
+
|
|
22
|
+
## Basic Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
11
25
|
const Resolver = require('class-resolver')
|
|
12
26
|
|
|
13
27
|
class ExampleClass {
|
|
@@ -26,32 +40,206 @@ class ExampleClass2 {
|
|
|
26
40
|
return 'fuga'
|
|
27
41
|
}
|
|
28
42
|
}
|
|
29
|
-
|
|
43
|
+
|
|
30
44
|
const resolver = new Resolver(new ExampleClass(), new ExampleClass2())
|
|
31
45
|
const c = resolver.resolve('hoge')
|
|
32
|
-
console.log(c.handle())
|
|
46
|
+
console.log(c.handle()) // Output: hoge
|
|
47
|
+
|
|
33
48
|
const c2 = resolver.resolve('fuga')
|
|
34
|
-
console.log(c2.handle())
|
|
49
|
+
console.log(c2.handle()) // Output: fuga
|
|
35
50
|
|
|
36
51
|
try {
|
|
37
|
-
resolver.resolve('xxx')
|
|
52
|
+
resolver.resolve('xxx') // This will throw an error
|
|
38
53
|
} catch (e) {
|
|
39
|
-
console.log(e)
|
|
54
|
+
console.log(e) // Error: Unsupported type: xxx
|
|
40
55
|
}
|
|
41
56
|
```
|
|
42
57
|
|
|
43
|
-
|
|
58
|
+
## Advanced Usage
|
|
59
|
+
|
|
60
|
+
### With TypeScript and Parameters
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import Resolver from 'class-resolver';
|
|
64
|
+
import { ResolveTarget } from 'class-resolver';
|
|
65
|
+
|
|
66
|
+
// Using generics for better type safety
|
|
67
|
+
class MessageFormatter implements ResolveTarget<[string, number], string> {
|
|
68
|
+
supports(type: string): boolean {
|
|
69
|
+
return type === 'greeting'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
handle(name: string, count: number): string {
|
|
73
|
+
return `Hello ${name}, this is message #${count}!`
|
|
74
|
+
}
|
|
75
|
+
}
|
|
44
76
|
|
|
77
|
+
class ErrorFormatter implements ResolveTarget<[string, number], string> {
|
|
78
|
+
supports(type: string): boolean {
|
|
79
|
+
return type === 'error'
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
handle(message: string, code: number): string {
|
|
83
|
+
return `Error ${code}: ${message}`
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Specify the generic type for better type safety
|
|
88
|
+
const resolver = new Resolver<ResolveTarget<[string, number], string>>(
|
|
89
|
+
new MessageFormatter(),
|
|
90
|
+
new ErrorFormatter()
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
// Using the greeting formatter
|
|
94
|
+
const greeting = resolver.resolve('greeting')
|
|
95
|
+
console.log(greeting.handle('John', 1)) // Output: Hello John, this is message #1!
|
|
96
|
+
|
|
97
|
+
// Using the error formatter
|
|
98
|
+
const error = resolver.resolve('error')
|
|
99
|
+
console.log(error.handle('Not Found', 404)) // Output: Error 404: Not Found
|
|
45
100
|
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
101
|
+
|
|
102
|
+
### Dynamic Resolver Registration
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// Specify the generic type for better type safety
|
|
106
|
+
const resolver = new Resolver<ResolveTarget<[string, number], string>>()
|
|
107
|
+
|
|
108
|
+
// Add resolvers after initialization
|
|
109
|
+
resolver.setUpdaters(new MessageFormatter(), new ErrorFormatter())
|
|
110
|
+
|
|
111
|
+
// Or add them one by one
|
|
112
|
+
resolver.addUpdater(new MessageFormatter())
|
|
113
|
+
resolver.addUpdater(new ErrorFormatter())
|
|
50
114
|
```
|
|
51
115
|
|
|
52
|
-
##
|
|
116
|
+
## Generic Type Support
|
|
117
|
+
|
|
118
|
+
From version 2.0.0, class-resolver supports generic types for better type safety:
|
|
53
119
|
|
|
120
|
+
```typescript
|
|
121
|
+
// Define the interface with generics
|
|
122
|
+
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
123
|
+
supports(type: string): boolean;
|
|
124
|
+
handle(...args: TArgs): TReturn;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Define a class that implements the interface with specific types
|
|
128
|
+
class StringFormatter implements ResolveTarget<[string], string> {
|
|
129
|
+
supports(type: string): boolean {
|
|
130
|
+
return type === 'string-format';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
handle(input: string): string {
|
|
134
|
+
return input.toUpperCase();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Create a resolver with the specific type
|
|
139
|
+
const resolver = new Resolver<ResolveTarget<[string], string>>(new StringFormatter());
|
|
140
|
+
const formatter = resolver.resolve('string-format');
|
|
141
|
+
const result = formatter.handle('hello'); // result is typed as string
|
|
54
142
|
```
|
|
143
|
+
|
|
144
|
+
## Use Cases
|
|
145
|
+
|
|
146
|
+
1. **Command Pattern Implementation**: Handle different types of commands with specific handlers
|
|
147
|
+
2. **Format Conversion**: Convert data between different formats based on type
|
|
148
|
+
3. **Request Processing**: Process different types of requests with dedicated handlers
|
|
149
|
+
4. **Plugin System**: Implement a plugin system where different plugins handle specific types of operations
|
|
150
|
+
5. **Message Formatting**: Format different types of messages with specific formatters
|
|
151
|
+
|
|
152
|
+
## Error Handling
|
|
153
|
+
|
|
154
|
+
The resolver will throw errors in the following cases:
|
|
155
|
+
- When no resolvers are registered: `"Unasigned resolve target."`
|
|
156
|
+
- When trying to resolve an unsupported type: `"Unsupported type: xxx"`
|
|
157
|
+
|
|
158
|
+
## Upgrade Guide
|
|
159
|
+
|
|
160
|
+
### Upgrading from 1.x to 2.0.0
|
|
161
|
+
|
|
162
|
+
Version 2.0.0 introduces generic type support for better type safety. This change is backward compatible for JavaScript users, but TypeScript users may need to update their code.
|
|
163
|
+
|
|
164
|
+
#### Changes for TypeScript Users
|
|
165
|
+
|
|
166
|
+
1. The `ResolveTarget` interface now supports generics:
|
|
167
|
+
```typescript
|
|
168
|
+
// Before (1.x)
|
|
169
|
+
interface ResolveTarget {
|
|
170
|
+
supports(type: string): boolean;
|
|
171
|
+
handle(...args: any[]): any;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// After (2.0.0)
|
|
175
|
+
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
176
|
+
supports(type: string): boolean;
|
|
177
|
+
handle(...args: TArgs): TReturn;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
2. The `Resolver` class now supports generics:
|
|
182
|
+
```typescript
|
|
183
|
+
// Before (1.x)
|
|
184
|
+
class Resolver {
|
|
185
|
+
// ...
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// After (2.0.0)
|
|
189
|
+
class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
190
|
+
// ...
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Migration Steps
|
|
195
|
+
|
|
196
|
+
1. If you're using TypeScript with default `any` types, your code should continue to work without changes.
|
|
197
|
+
|
|
198
|
+
2. To take advantage of the improved type safety, update your class implementations:
|
|
199
|
+
```typescript
|
|
200
|
+
// Before (1.x)
|
|
201
|
+
class MyHandler implements ResolveTarget {
|
|
202
|
+
supports(type: string): boolean {
|
|
203
|
+
return type === 'my-type';
|
|
204
|
+
}
|
|
205
|
+
handle(name: string): string {
|
|
206
|
+
return `Hello ${name}`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// After (2.0.0)
|
|
211
|
+
class MyHandler implements ResolveTarget<[string], string> {
|
|
212
|
+
supports(type: string): boolean {
|
|
213
|
+
return type === 'my-type';
|
|
214
|
+
}
|
|
215
|
+
handle(name: string): string {
|
|
216
|
+
return `Hello ${name}`;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
3. When creating a new Resolver, specify the generic type:
|
|
222
|
+
```typescript
|
|
223
|
+
// Before (1.x)
|
|
224
|
+
const resolver = new Resolver(new MyHandler());
|
|
225
|
+
|
|
226
|
+
// After (2.0.0)
|
|
227
|
+
const resolver = new Resolver<ResolveTarget<[string], string>>(new MyHandler());
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
4. If you have mixed handler types, you can use a union type or keep using the default `any` type:
|
|
231
|
+
```typescript
|
|
232
|
+
// Using union type
|
|
233
|
+
type MyHandlers = ResolveTarget<[string], string> | ResolveTarget<[number], boolean>;
|
|
234
|
+
const resolver = new Resolver<MyHandlers>(new StringHandler(), new NumberHandler());
|
|
235
|
+
|
|
236
|
+
// Or keep using the default any type
|
|
237
|
+
const resolver = new Resolver(new StringHandler(), new NumberHandler());
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Contributing
|
|
241
|
+
|
|
242
|
+
```bash
|
|
55
243
|
$ npm install
|
|
56
244
|
$ git checkout -b YOUR_TOPIC_BRANCH
|
|
57
245
|
$ npm test
|
|
@@ -59,4 +247,8 @@ $ npm run build
|
|
|
59
247
|
$ git add ./
|
|
60
248
|
$ git commit -m "YOUR UPDATE DESCRIPTION"
|
|
61
249
|
$ git push YOUR_ORIGIN YOUR_TOPIC_BRANCH
|
|
62
|
-
```
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
18
|
};
|
|
5
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./interface"), exports);
|
|
6
21
|
const resolver_1 = __importDefault(require("./resolver"));
|
|
7
22
|
exports.default = resolver_1.default;
|
|
23
|
+
// Export for CommonJS compatibility
|
|
24
|
+
// @ts-ignore
|
|
8
25
|
module.exports = resolver_1.default;
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../libs/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,0DAAiC;AACjC,kBAAe,kBAAQ,CAAA;AACvB,oCAAoC;AACpC,aAAa;AACb,MAAM,CAAC,OAAO,GAAG,kBAAQ,CAAA"}
|
package/dist/interface.d.ts
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface that classes which are targets for the resolver should implement
|
|
3
|
+
*/
|
|
4
|
+
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
5
|
+
/**
|
|
6
|
+
* Determines whether the specified type is supported
|
|
7
|
+
* @param type The type to check for support
|
|
8
|
+
* @returns true if supported, false otherwise
|
|
9
|
+
*/
|
|
10
|
+
supports(type: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Handles the request
|
|
13
|
+
* @param args Arguments needed for processing
|
|
14
|
+
* @returns Processing result
|
|
15
|
+
*/
|
|
16
|
+
handle(...args: TArgs): TReturn;
|
|
17
|
+
}
|
|
1
18
|
export declare namespace interfaces {
|
|
2
|
-
interface ResolveTarget {
|
|
19
|
+
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
3
20
|
supports(type: string): boolean;
|
|
4
|
-
handle(...args:
|
|
21
|
+
handle(...args: TArgs): TReturn;
|
|
5
22
|
}
|
|
6
23
|
}
|
package/dist/interface.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../libs/interface.ts"],"names":[],"mappings":""}
|
package/dist/resolver.d.ts
CHANGED
|
@@ -1,12 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { ResolveTarget } from './interface';
|
|
2
|
+
/**
|
|
3
|
+
* Resolver class implementing the Chain of Responsibility pattern
|
|
4
|
+
* Resolves handlers for specific types
|
|
5
|
+
*/
|
|
6
|
+
declare class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
7
|
+
/**
|
|
8
|
+
* Array of registered resolver targets
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
private updaters;
|
|
12
|
+
/**
|
|
13
|
+
* Initializes the resolver
|
|
14
|
+
* @param args Initial resolver targets
|
|
15
|
+
*/
|
|
16
|
+
constructor(...args: TBase[]);
|
|
17
|
+
/**
|
|
18
|
+
* Processes an array of arguments
|
|
19
|
+
* @param args Array of resolver targets
|
|
20
|
+
* @returns Processed array
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
private getArgs;
|
|
24
|
+
/**
|
|
25
|
+
* Sets resolver targets
|
|
26
|
+
* @param updaters Array of resolver targets
|
|
27
|
+
*/
|
|
28
|
+
set(updaters: TBase[]): void;
|
|
29
|
+
/**
|
|
30
|
+
* Sets resolver targets (variadic version)
|
|
31
|
+
* @param args Resolver targets
|
|
32
|
+
*/
|
|
33
|
+
setUpdaters(...args: TBase[]): void;
|
|
34
|
+
/**
|
|
35
|
+
* Adds a resolver target
|
|
36
|
+
* @param updater Resolver target to add
|
|
37
|
+
*/
|
|
38
|
+
addUpdater(updater: TBase): void;
|
|
39
|
+
/**
|
|
40
|
+
* Resolves a resolver target for the specified type
|
|
41
|
+
* @param type Type to resolve
|
|
42
|
+
* @returns Resolved resolver target
|
|
43
|
+
* @throws {Error} When no resolver targets are registered
|
|
44
|
+
* @throws {Error} When no resolver target supporting the specified type is found
|
|
45
|
+
*/
|
|
46
|
+
resolve(type: string): TBase;
|
|
11
47
|
}
|
|
12
48
|
export default Resolver;
|
package/dist/resolver.js
CHANGED
|
@@ -1,29 +1,71 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Resolver class implementing the Chain of Responsibility pattern
|
|
5
|
+
* Resolves handlers for specific types
|
|
6
|
+
*/
|
|
3
7
|
class Resolver {
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the resolver
|
|
10
|
+
* @param args Initial resolver targets
|
|
11
|
+
*/
|
|
4
12
|
constructor(...args) {
|
|
5
|
-
|
|
6
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Array of registered resolver targets
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
this.updaters = [];
|
|
18
|
+
if (args.length > 0) {
|
|
19
|
+
this.set(args);
|
|
20
|
+
}
|
|
7
21
|
}
|
|
8
|
-
|
|
9
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Processes an array of arguments
|
|
24
|
+
* @param args Array of resolver targets
|
|
25
|
+
* @returns Processed array
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
getArgs(args) {
|
|
29
|
+
return [...args];
|
|
10
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Sets resolver targets
|
|
33
|
+
* @param updaters Array of resolver targets
|
|
34
|
+
*/
|
|
11
35
|
set(updaters) {
|
|
12
|
-
this.
|
|
36
|
+
this.updaters = updaters;
|
|
13
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Sets resolver targets (variadic version)
|
|
40
|
+
* @param args Resolver targets
|
|
41
|
+
*/
|
|
14
42
|
setUpdaters(...args) {
|
|
15
43
|
this.set(this.getArgs(args));
|
|
16
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Adds a resolver target
|
|
47
|
+
* @param updater Resolver target to add
|
|
48
|
+
*/
|
|
17
49
|
addUpdater(updater) {
|
|
18
|
-
this.
|
|
50
|
+
this.updaters.push(updater);
|
|
19
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolves a resolver target for the specified type
|
|
54
|
+
* @param type Type to resolve
|
|
55
|
+
* @returns Resolved resolver target
|
|
56
|
+
* @throws {Error} When no resolver targets are registered
|
|
57
|
+
* @throws {Error} When no resolver target supporting the specified type is found
|
|
58
|
+
*/
|
|
20
59
|
resolve(type) {
|
|
21
|
-
if (this.
|
|
60
|
+
if (this.updaters.length < 1) {
|
|
22
61
|
throw new Error('Unasigned resolve target.');
|
|
23
|
-
|
|
24
|
-
|
|
62
|
+
}
|
|
63
|
+
const target = this.updaters.find(updater => updater.supports(type));
|
|
64
|
+
if (!target) {
|
|
25
65
|
throw new Error(`Unsupported type: ${type}`);
|
|
26
|
-
|
|
66
|
+
}
|
|
67
|
+
return target;
|
|
27
68
|
}
|
|
28
69
|
}
|
|
29
70
|
exports.default = Resolver;
|
|
71
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../libs/resolver.ts"],"names":[],"mappings":";;AAEA;;;GAGG;AACH,MAAM,QAAQ;IAOZ;;;OAGG;IACH,YAAY,GAAG,IAAa;QAV5B;;;WAGG;QACK,aAAQ,GAAY,EAAE,CAAC;QAO7B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,OAAO,CAAC,IAAa;QAC3B,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACnB,CAAC;IAED;;;OAGG;IACI,GAAG,CAAC,QAAiB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACI,WAAW,CAAC,GAAG,IAAa;QACjC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACI,UAAU,CAAC,OAAc;QAC9B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;;OAMG;IACI,OAAO,CAAC,IAAY;QACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAErE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,kBAAe,QAAQ,CAAC"}
|
package/index.js
CHANGED
package/libs/index.ts
CHANGED
package/libs/interface.ts
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Interface that classes which are targets for the resolver should implement
|
|
3
|
+
*/
|
|
4
|
+
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
5
|
+
/**
|
|
6
|
+
* Determines whether the specified type is supported
|
|
7
|
+
* @param type The type to check for support
|
|
8
|
+
* @returns true if supported, false otherwise
|
|
9
|
+
*/
|
|
2
10
|
supports(type: string): boolean
|
|
3
|
-
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Handles the request
|
|
14
|
+
* @param args Arguments needed for processing
|
|
15
|
+
* @returns Processing result
|
|
16
|
+
*/
|
|
17
|
+
handle(...args: TArgs): TReturn
|
|
4
18
|
}
|
|
19
|
+
|
|
20
|
+
// Maintain namespace for backward compatibility
|
|
5
21
|
export namespace interfaces {
|
|
6
|
-
export interface ResolveTarget {
|
|
22
|
+
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
7
23
|
supports(type: string): boolean
|
|
8
|
-
handle(...args:
|
|
24
|
+
handle(...args: TArgs): TReturn
|
|
9
25
|
}
|
|
10
26
|
}
|
package/libs/resolver.ts
CHANGED
|
@@ -1,29 +1,80 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { ResolveTarget } from './interface'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolver class implementing the Chain of Responsibility pattern
|
|
5
|
+
* Resolves handlers for specific types
|
|
6
|
+
*/
|
|
7
|
+
class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
8
|
+
/**
|
|
9
|
+
* Array of registered resolver targets
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
private updaters: TBase[] = [];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Initializes the resolver
|
|
16
|
+
* @param args Initial resolver targets
|
|
17
|
+
*/
|
|
18
|
+
constructor(...args: TBase[]) {
|
|
19
|
+
if (args.length > 0) {
|
|
20
|
+
this.set(args);
|
|
21
|
+
}
|
|
9
22
|
}
|
|
10
|
-
|
|
11
|
-
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Processes an array of arguments
|
|
26
|
+
* @param args Array of resolver targets
|
|
27
|
+
* @returns Processed array
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
private getArgs(args: TBase[]): TBase[] {
|
|
31
|
+
return [...args];
|
|
12
32
|
}
|
|
13
|
-
|
|
14
|
-
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sets resolver targets
|
|
36
|
+
* @param updaters Array of resolver targets
|
|
37
|
+
*/
|
|
38
|
+
public set(updaters: TBase[]): void {
|
|
39
|
+
this.updaters = updaters;
|
|
15
40
|
}
|
|
16
|
-
|
|
17
|
-
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Sets resolver targets (variadic version)
|
|
44
|
+
* @param args Resolver targets
|
|
45
|
+
*/
|
|
46
|
+
public setUpdaters(...args: TBase[]): void {
|
|
47
|
+
this.set(this.getArgs(args));
|
|
18
48
|
}
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Adds a resolver target
|
|
52
|
+
* @param updater Resolver target to add
|
|
53
|
+
*/
|
|
54
|
+
public addUpdater(updater: TBase): void {
|
|
55
|
+
this.updaters.push(updater);
|
|
21
56
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Resolves a resolver target for the specified type
|
|
60
|
+
* @param type Type to resolve
|
|
61
|
+
* @returns Resolved resolver target
|
|
62
|
+
* @throws {Error} When no resolver targets are registered
|
|
63
|
+
* @throws {Error} When no resolver target supporting the specified type is found
|
|
64
|
+
*/
|
|
65
|
+
public resolve(type: string): TBase {
|
|
66
|
+
if (this.updaters.length < 1) {
|
|
67
|
+
throw new Error('Unasigned resolve target.');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const target = this.updaters.find(updater => updater.supports(type));
|
|
71
|
+
|
|
72
|
+
if (!target) {
|
|
73
|
+
throw new Error(`Unsupported type: ${type}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return target;
|
|
27
77
|
}
|
|
28
78
|
}
|
|
29
|
-
|
|
79
|
+
|
|
80
|
+
export default Resolver;
|
package/package.json
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "class-resolver",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Simple class resolver.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"build": "tsc",
|
|
8
|
-
"test": "jest"
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"test:watch": "jest --watch",
|
|
11
|
+
"test:dev": "jest --watch --silent=false --verbose false --coverage",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
9
13
|
},
|
|
10
|
-
"keywords": [
|
|
14
|
+
"keywords": [
|
|
15
|
+
"resolver",
|
|
16
|
+
"chain-of-responsibility",
|
|
17
|
+
"typescript"
|
|
18
|
+
],
|
|
11
19
|
"author": "Hidetaka Okamoto <info@wp-kyoto.net> (https://wp-kyoto.net)",
|
|
12
20
|
"license": "MIT",
|
|
13
21
|
"devDependencies": {
|
|
14
|
-
"@types/jest": "^
|
|
15
|
-
"@types/node": "^
|
|
16
|
-
"jest": "^
|
|
17
|
-
"ts-jest": "^
|
|
18
|
-
"typescript": "^
|
|
22
|
+
"@types/jest": "^29.5.0",
|
|
23
|
+
"@types/node": "^20.0.0",
|
|
24
|
+
"jest": "^29.5.0",
|
|
25
|
+
"ts-jest": "^29.1.0",
|
|
26
|
+
"typescript": "^5.0.0"
|
|
19
27
|
},
|
|
20
28
|
"jest": {
|
|
21
29
|
"moduleFileExtensions": [
|
|
@@ -24,15 +32,17 @@
|
|
|
24
32
|
"js"
|
|
25
33
|
],
|
|
26
34
|
"transform": {
|
|
27
|
-
"^.+\\.(ts|tsx)$": "ts-jest"
|
|
28
|
-
},
|
|
29
|
-
"globals": {
|
|
30
|
-
"ts-jest": {
|
|
31
|
-
"tsConfigFile": "tsconfig.json"
|
|
32
|
-
}
|
|
35
|
+
"^.+\\.(ts|tsx)$": ["ts-jest", { "tsconfig": "tsconfig.json" }]
|
|
33
36
|
},
|
|
34
37
|
"testMatch": [
|
|
35
38
|
"**/__tests__/*.+(ts|tsx|js)"
|
|
36
39
|
]
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/hideokamoto/class-resolver.git"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=14.0.0"
|
|
37
47
|
}
|
|
38
48
|
}
|