class-resolver 2.0.0 → 2.1.1
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 +85 -5
- package/dist/interface.d.ts +4 -4
- package/dist/resolver.d.ts +2 -2
- package/dist/resolver.js +6 -2
- package/dist/resolver.js.map +1 -1
- package/libs/interface.ts +4 -4
- package/libs/resolver.ts +8 -4
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -119,8 +119,8 @@ From version 2.0.0, class-resolver supports generic types for better type safety
|
|
|
119
119
|
|
|
120
120
|
```typescript
|
|
121
121
|
// Define the interface with generics
|
|
122
|
-
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
123
|
-
supports(type:
|
|
122
|
+
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
|
|
123
|
+
supports(type: TType): boolean;
|
|
124
124
|
handle(...args: TArgs): TReturn;
|
|
125
125
|
}
|
|
126
126
|
|
|
@@ -141,6 +141,67 @@ const formatter = resolver.resolve('string-format');
|
|
|
141
141
|
const result = formatter.handle('hello'); // result is typed as string
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
+
### Advanced Type Support
|
|
145
|
+
|
|
146
|
+
You can now use any type for the `supports` method, not just strings. This is particularly useful for handling complex objects like Stripe events:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// Define a complex event type
|
|
150
|
+
interface StripeEvent {
|
|
151
|
+
id: string;
|
|
152
|
+
type: string;
|
|
153
|
+
data: {
|
|
154
|
+
object: {
|
|
155
|
+
id: string;
|
|
156
|
+
amount: number;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Create handlers for specific event types
|
|
162
|
+
class PaymentEventHandler implements ResolveTarget<[StripeEvent], string, StripeEvent> {
|
|
163
|
+
supports(event: StripeEvent): boolean {
|
|
164
|
+
return event.type === 'payment_intent.succeeded';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
handle(event: StripeEvent): string {
|
|
168
|
+
return `Payment succeeded: ${event.data.object.amount}`;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
class RefundEventHandler implements ResolveTarget<[StripeEvent], string, StripeEvent> {
|
|
173
|
+
supports(event: StripeEvent): boolean {
|
|
174
|
+
return event.type === 'charge.refunded';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
handle(event: StripeEvent): string {
|
|
178
|
+
return `Refund processed: ${event.data.object.amount}`;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Create a resolver that handles StripeEvent types
|
|
183
|
+
const resolver = new Resolver<ResolveTarget<[StripeEvent], string, StripeEvent>, StripeEvent>(
|
|
184
|
+
new PaymentEventHandler(),
|
|
185
|
+
new RefundEventHandler()
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Handle different event types
|
|
189
|
+
const paymentEvent: StripeEvent = {
|
|
190
|
+
id: 'evt_123',
|
|
191
|
+
type: 'payment_intent.succeeded',
|
|
192
|
+
data: { object: { id: 'pi_123', amount: 1000 } }
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const handler = resolver.resolve(paymentEvent);
|
|
196
|
+
console.log(handler.handle(paymentEvent)); // Output: Payment succeeded: 1000
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
This advanced type support allows you to:
|
|
200
|
+
- Use complex objects as type identifiers instead of simple strings
|
|
201
|
+
- Maintain full type safety throughout the resolution process
|
|
202
|
+
- Handle domain-specific objects like Stripe events, database records, or custom business objects
|
|
203
|
+
- Create more expressive and type-safe event handling systems
|
|
204
|
+
|
|
144
205
|
## Use Cases
|
|
145
206
|
|
|
146
207
|
1. **Command Pattern Implementation**: Handle different types of commands with specific handlers
|
|
@@ -172,8 +233,8 @@ Version 2.0.0 introduces generic type support for better type safety. This chang
|
|
|
172
233
|
}
|
|
173
234
|
|
|
174
235
|
// After (2.0.0)
|
|
175
|
-
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
176
|
-
supports(type:
|
|
236
|
+
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
|
|
237
|
+
supports(type: TType): boolean;
|
|
177
238
|
handle(...args: TArgs): TReturn;
|
|
178
239
|
}
|
|
179
240
|
```
|
|
@@ -186,11 +247,30 @@ Version 2.0.0 introduces generic type support for better type safety. This chang
|
|
|
186
247
|
}
|
|
187
248
|
|
|
188
249
|
// After (2.0.0)
|
|
189
|
-
class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
250
|
+
class Resolver<TBase extends ResolveTarget<any[], any, any> = ResolveTarget<any[], any, any>, TType = string> {
|
|
190
251
|
// ...
|
|
191
252
|
}
|
|
192
253
|
```
|
|
193
254
|
|
|
255
|
+
3. **New in 2.0.0**: You can now specify custom types for the `supports` method:
|
|
256
|
+
```typescript
|
|
257
|
+
// Use custom types instead of strings
|
|
258
|
+
interface CustomEvent {
|
|
259
|
+
type: string;
|
|
260
|
+
data: any;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
class CustomHandler implements ResolveTarget<[CustomEvent], string, CustomEvent> {
|
|
264
|
+
supports(event: CustomEvent): boolean {
|
|
265
|
+
return event.type === 'custom-type';
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
handle(event: CustomEvent): string {
|
|
269
|
+
return `Handled: ${event.type}`;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
194
274
|
#### Migration Steps
|
|
195
275
|
|
|
196
276
|
1. If you're using TypeScript with default `any` types, your code should continue to work without changes.
|
package/dist/interface.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Interface that classes which are targets for the resolver should implement
|
|
3
3
|
*/
|
|
4
|
-
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
4
|
+
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
|
|
5
5
|
/**
|
|
6
6
|
* Determines whether the specified type is supported
|
|
7
7
|
* @param type The type to check for support
|
|
8
8
|
* @returns true if supported, false otherwise
|
|
9
9
|
*/
|
|
10
|
-
supports(type:
|
|
10
|
+
supports(type: TType): boolean;
|
|
11
11
|
/**
|
|
12
12
|
* Handles the request
|
|
13
13
|
* @param args Arguments needed for processing
|
|
@@ -16,8 +16,8 @@ export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
|
16
16
|
handle(...args: TArgs): TReturn;
|
|
17
17
|
}
|
|
18
18
|
export declare namespace interfaces {
|
|
19
|
-
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
20
|
-
supports(type:
|
|
19
|
+
interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
|
|
20
|
+
supports(type: TType): boolean;
|
|
21
21
|
handle(...args: TArgs): TReturn;
|
|
22
22
|
}
|
|
23
23
|
}
|
package/dist/resolver.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ResolveTarget } from './interface';
|
|
|
3
3
|
* Resolver class implementing the Chain of Responsibility pattern
|
|
4
4
|
* Resolves handlers for specific types
|
|
5
5
|
*/
|
|
6
|
-
declare class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
6
|
+
declare class Resolver<TBase extends ResolveTarget<any[], any, any> = ResolveTarget<any[], any, any>, TType = string> {
|
|
7
7
|
/**
|
|
8
8
|
* Array of registered resolver targets
|
|
9
9
|
* @private
|
|
@@ -43,6 +43,6 @@ declare class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
|
43
43
|
* @throws {Error} When no resolver targets are registered
|
|
44
44
|
* @throws {Error} When no resolver target supporting the specified type is found
|
|
45
45
|
*/
|
|
46
|
-
resolve(type:
|
|
46
|
+
resolve(type: TType): TBase;
|
|
47
47
|
}
|
|
48
48
|
export default Resolver;
|
package/dist/resolver.js
CHANGED
|
@@ -58,11 +58,15 @@ class Resolver {
|
|
|
58
58
|
*/
|
|
59
59
|
resolve(type) {
|
|
60
60
|
if (this.updaters.length < 1) {
|
|
61
|
-
throw new Error('
|
|
61
|
+
throw new Error('Unassigned resolve target.');
|
|
62
62
|
}
|
|
63
63
|
const target = this.updaters.find(updater => updater.supports(type));
|
|
64
64
|
if (!target) {
|
|
65
|
-
|
|
65
|
+
// Determine the string representation of the unsupported type
|
|
66
|
+
// If it's a non-null object, use JSON.stringify for detailed output
|
|
67
|
+
// Otherwise, use String() for basic conversion
|
|
68
|
+
const typeString = typeof type === 'object' && type !== null ? JSON.stringify(type) : String(type);
|
|
69
|
+
throw new Error(`Unsupported type: ${typeString}`);
|
|
66
70
|
}
|
|
67
71
|
return target;
|
|
68
72
|
}
|
package/dist/resolver.js.map
CHANGED
|
@@ -1 +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,
|
|
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,IAAW;QACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,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,8DAA8D;YAC9D,oEAAoE;YACpE,+CAA+C;YAC/C,MAAM,UAAU,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACnG,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,kBAAe,QAAQ,CAAC"}
|
package/libs/interface.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Interface that classes which are targets for the resolver should implement
|
|
3
3
|
*/
|
|
4
|
-
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
4
|
+
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
|
|
5
5
|
/**
|
|
6
6
|
* Determines whether the specified type is supported
|
|
7
7
|
* @param type The type to check for support
|
|
8
8
|
* @returns true if supported, false otherwise
|
|
9
9
|
*/
|
|
10
|
-
supports(type:
|
|
10
|
+
supports(type: TType): boolean
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Handles the request
|
|
@@ -19,8 +19,8 @@ export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
|
19
19
|
|
|
20
20
|
// Maintain namespace for backward compatibility
|
|
21
21
|
export namespace interfaces {
|
|
22
|
-
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any> {
|
|
23
|
-
supports(type:
|
|
22
|
+
export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
|
|
23
|
+
supports(type: TType): boolean
|
|
24
24
|
handle(...args: TArgs): TReturn
|
|
25
25
|
}
|
|
26
26
|
}
|
package/libs/resolver.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ResolveTarget } from './interface'
|
|
|
4
4
|
* Resolver class implementing the Chain of Responsibility pattern
|
|
5
5
|
* Resolves handlers for specific types
|
|
6
6
|
*/
|
|
7
|
-
class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
7
|
+
class Resolver<TBase extends ResolveTarget<any[], any, any> = ResolveTarget<any[], any, any>, TType = string> {
|
|
8
8
|
/**
|
|
9
9
|
* Array of registered resolver targets
|
|
10
10
|
* @private
|
|
@@ -62,15 +62,19 @@ class Resolver<TBase extends ResolveTarget = ResolveTarget> {
|
|
|
62
62
|
* @throws {Error} When no resolver targets are registered
|
|
63
63
|
* @throws {Error} When no resolver target supporting the specified type is found
|
|
64
64
|
*/
|
|
65
|
-
public resolve(type:
|
|
65
|
+
public resolve(type: TType): TBase {
|
|
66
66
|
if (this.updaters.length < 1) {
|
|
67
|
-
throw new Error('
|
|
67
|
+
throw new Error('Unassigned resolve target.');
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
const target = this.updaters.find(updater => updater.supports(type));
|
|
71
71
|
|
|
72
72
|
if (!target) {
|
|
73
|
-
|
|
73
|
+
// Determine the string representation of the unsupported type
|
|
74
|
+
// If it's a non-null object, use JSON.stringify for detailed output
|
|
75
|
+
// Otherwise, use String() for basic conversion
|
|
76
|
+
const typeString = typeof type === 'object' && type !== null ? JSON.stringify(type) : String(type);
|
|
77
|
+
throw new Error(`Unsupported type: ${typeString}`);
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
return target;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "class-resolver",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Simple class resolver.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -32,7 +32,12 @@
|
|
|
32
32
|
"js"
|
|
33
33
|
],
|
|
34
34
|
"transform": {
|
|
35
|
-
"^.+\\.(ts|tsx)$": [
|
|
35
|
+
"^.+\\.(ts|tsx)$": [
|
|
36
|
+
"ts-jest",
|
|
37
|
+
{
|
|
38
|
+
"tsconfig": "tsconfig.json"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
36
41
|
},
|
|
37
42
|
"testMatch": [
|
|
38
43
|
"**/__tests__/*.+(ts|tsx|js)"
|