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 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: string): boolean;
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: string): boolean;
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.
@@ -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: string): boolean;
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: string): boolean;
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
  }
@@ -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: string): TBase;
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('Unasigned resolve target.');
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
- throw new Error(`Unsupported type: ${type}`);
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
  }
@@ -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,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"}
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: string): boolean
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: string): boolean
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: string): TBase {
65
+ public resolve(type: TType): TBase {
66
66
  if (this.updaters.length < 1) {
67
- throw new Error('Unasigned resolve target.');
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
- throw new Error(`Unsupported type: ${type}`);
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.0.0",
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)$": ["ts-jest", { "tsconfig": "tsconfig.json" }]
35
+ "^.+\\.(ts|tsx)$": [
36
+ "ts-jest",
37
+ {
38
+ "tsconfig": "tsconfig.json"
39
+ }
40
+ ]
36
41
  },
37
42
  "testMatch": [
38
43
  "**/__tests__/*.+(ts|tsx|js)"