class-resolver 2.2.0 → 4.0.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
@@ -12,6 +12,9 @@ A lightweight TypeScript/JavaScript library for implementing the Chain of Respon
12
12
  - Generic type support for better type safety
13
13
  - **Fallback handler support for graceful handling of unsupported types**
14
14
  - **Method chaining support for fluent API usage**
15
+ - **🎯 NEW: Multiple handler execution (resolveAll, handleAll)**
16
+ - **🎯 NEW: Priority-based handler resolution**
17
+ - **🎯 NEW: Async handler support (handleAllAsync, handleAllSequential)**
15
18
 
16
19
  ## Installation
17
20
 
@@ -252,21 +255,268 @@ This advanced type support allows you to:
252
255
  - Handle domain-specific objects like Stripe events, database records, or custom business objects
253
256
  - Create more expressive and type-safe event handling systems
254
257
 
258
+ ## Breaking Changes in v3.0.0
259
+
260
+ ### `resolve()` Method Behavior Change
261
+
262
+ **Important**: The `resolve()` method now returns the **highest priority handler** instead of the first matching handler based on registration order.
263
+
264
+ #### Before (v2.x)
265
+ ```typescript
266
+ const resolver = new Resolver(handler1, handler2, handler3);
267
+ const result = resolver.resolve('type'); // Returns handler1 (first registered)
268
+ ```
269
+
270
+ #### After (v3.0.0)
271
+ ```typescript
272
+ // Without priority - behavior unchanged (returns first matching handler)
273
+ const resolver = new Resolver(handler1, handler2, handler3);
274
+ const result = resolver.resolve('type'); // Still returns handler1
275
+
276
+ // With priority - returns highest priority handler
277
+ class HighPriority implements PrioritizedResolveTarget {
278
+ priority = 100;
279
+ // ...
280
+ }
281
+ class LowPriority implements PrioritizedResolveTarget {
282
+ priority = 10;
283
+ // ...
284
+ }
285
+
286
+ const resolver = new Resolver(lowPriority, highPriority);
287
+ const result = resolver.resolve('type'); // Returns highPriority (priority: 100)
288
+ ```
289
+
290
+ **Migration Guide**: If you rely on registration order and don't want priority-based resolution:
291
+ - Continue using handlers without the `priority` property - they will maintain registration order (all have default priority of 0)
292
+ - Or explicitly set the same priority on all handlers to maintain registration order
293
+
294
+ ## New Features in v3.0.0
295
+
296
+ ### Multiple Handler Execution
297
+
298
+ Execute all matching handlers for a single event type. Perfect for webhook fanout patterns where one event needs multiple processors.
299
+
300
+ ```typescript
301
+ import Resolver from 'class-resolver';
302
+ import { ResolveTarget } from 'class-resolver';
303
+
304
+ interface StripeEvent {
305
+ type: string;
306
+ data: { amount: number };
307
+ }
308
+
309
+ class AccountingHandler implements ResolveTarget<[StripeEvent], string, StripeEvent> {
310
+ supports(event: StripeEvent): boolean {
311
+ return event.type === 'payment.succeeded';
312
+ }
313
+ handle(event: StripeEvent): string {
314
+ return `Accounting: Recorded ${event.data.amount}`;
315
+ }
316
+ }
317
+
318
+ class EmailHandler implements ResolveTarget<[StripeEvent], string, StripeEvent> {
319
+ supports(event: StripeEvent): boolean {
320
+ return event.type === 'payment.succeeded';
321
+ }
322
+ handle(event: StripeEvent): string {
323
+ return `Email: Sent confirmation for ${event.data.amount}`;
324
+ }
325
+ }
326
+
327
+ class AnalyticsHandler implements ResolveTarget<[StripeEvent], string, StripeEvent> {
328
+ supports(event: StripeEvent): boolean {
329
+ return event.type === 'payment.succeeded';
330
+ }
331
+ handle(event: StripeEvent): string {
332
+ return `Analytics: Logged ${event.data.amount}`;
333
+ }
334
+ }
335
+
336
+ const resolver = new Resolver<ResolveTarget<[StripeEvent], string, StripeEvent>, StripeEvent>(
337
+ new AccountingHandler(),
338
+ new EmailHandler(),
339
+ new AnalyticsHandler()
340
+ );
341
+
342
+ const event: StripeEvent = {
343
+ type: 'payment.succeeded',
344
+ data: { amount: 1000 }
345
+ };
346
+
347
+ // Execute ALL matching handlers
348
+ const results = resolver.handleAll(event, event);
349
+ // Results: [
350
+ // 'Accounting: Recorded 1000',
351
+ // 'Email: Sent confirmation for 1000',
352
+ // 'Analytics: Logged 1000'
353
+ // ]
354
+
355
+ // Or get all matching handlers
356
+ const handlers = resolver.resolveAll(event);
357
+ // handlers.length === 3
358
+ ```
359
+
360
+ ### Priority-Based Handler Resolution
361
+
362
+ Control execution order with priority levels. Higher priority handlers execute first.
363
+
364
+ ```typescript
365
+ import { PrioritizedResolveTarget } from 'class-resolver';
366
+
367
+ class ValidationHandler implements PrioritizedResolveTarget<[any], boolean, string> {
368
+ priority = 100; // Highest priority
369
+
370
+ supports(type: string): boolean {
371
+ return type === 'webhook';
372
+ }
373
+
374
+ handle(data: any): boolean {
375
+ return data !== null && data !== undefined;
376
+ }
377
+ }
378
+
379
+ class BusinessLogicHandler implements PrioritizedResolveTarget<[any], string, string> {
380
+ priority = 50; // Medium priority
381
+
382
+ supports(type: string): boolean {
383
+ return type === 'webhook';
384
+ }
385
+
386
+ handle(data: any): string {
387
+ return `Processed: ${JSON.stringify(data)}`;
388
+ }
389
+ }
390
+
391
+ class LoggingHandler implements PrioritizedResolveTarget<[any], void, string> {
392
+ priority = 10; // Lowest priority
393
+
394
+ supports(type: string): boolean {
395
+ return type === 'webhook';
396
+ }
397
+
398
+ handle(data: any): void {
399
+ console.log(`Logged: ${JSON.stringify(data)}`);
400
+ }
401
+ }
402
+
403
+ const resolver = new Resolver<PrioritizedResolveTarget<[any], any, string>, string>(
404
+ new LoggingHandler(), // Registered third
405
+ new ValidationHandler(), // Registered first
406
+ new BusinessLogicHandler() // Registered second
407
+ );
408
+
409
+ // Handlers execute in PRIORITY order (not registration order):
410
+ // 1. ValidationHandler (priority: 100)
411
+ // 2. BusinessLogicHandler (priority: 50)
412
+ // 3. LoggingHandler (priority: 10)
413
+ const results = resolver.handleAll('webhook', { test: true });
414
+ ```
415
+
416
+ ### Async Handler Support
417
+
418
+ Execute async handlers in parallel or sequentially.
419
+
420
+ ```typescript
421
+ import { AsyncResolveTarget } from 'class-resolver';
422
+
423
+ class SaveToDBHandler implements AsyncResolveTarget<[any], string, string> {
424
+ supports(type: string): boolean {
425
+ return type === 'payment';
426
+ }
427
+
428
+ async handle(data: any): Promise<string> {
429
+ // Simulate DB save
430
+ await new Promise(resolve => setTimeout(resolve, 100));
431
+ return 'Saved to DB';
432
+ }
433
+ }
434
+
435
+ class SendWebhookHandler implements AsyncResolveTarget<[any], string, string> {
436
+ supports(type: string): boolean {
437
+ return type === 'payment';
438
+ }
439
+
440
+ async handle(data: any): Promise<string> {
441
+ // Simulate external API call
442
+ await new Promise(resolve => setTimeout(resolve, 200));
443
+ return 'Webhook sent';
444
+ }
445
+ }
446
+
447
+ const resolver = new Resolver<AsyncResolveTarget<[any], string, string>, string>(
448
+ new SaveToDBHandler(),
449
+ new SendWebhookHandler()
450
+ );
451
+
452
+ // Execute handlers in PARALLEL (fastest)
453
+ const results = await resolver.handleAllAsync('payment', { amount: 1000 });
454
+ // Results: ['Saved to DB', 'Webhook sent']
455
+ // Total time: ~200ms (not 300ms)
456
+
457
+ // Or execute SEQUENTIALLY (ordered, stops on error)
458
+ const results2 = await resolver.handleAllSequential('payment', { amount: 1000 });
459
+ // Results: ['Saved to DB', 'Webhook sent']
460
+ // Total time: ~300ms
461
+ ```
462
+
463
+ ### Priority + Async Combined
464
+
465
+ ```typescript
466
+ import { PrioritizedAsyncResolveTarget } from 'class-resolver';
467
+
468
+ class ValidationHandler implements PrioritizedAsyncResolveTarget<[any], boolean, string> {
469
+ priority = 100;
470
+
471
+ supports(type: string): boolean {
472
+ return type === 'order';
473
+ }
474
+
475
+ async handle(data: any): Promise<boolean> {
476
+ // Async validation
477
+ return data.amount > 0;
478
+ }
479
+ }
480
+
481
+ class ProcessHandler implements PrioritizedAsyncResolveTarget<[any], string, string> {
482
+ priority = 50;
483
+
484
+ supports(type: string): boolean {
485
+ return type === 'order';
486
+ }
487
+
488
+ async handle(data: any): Promise<string> {
489
+ return `Processed order ${data.id}`;
490
+ }
491
+ }
492
+
493
+ const resolver = new Resolver<PrioritizedAsyncResolveTarget<[any], any, string>, string>(
494
+ new ProcessHandler(), // priority: 50
495
+ new ValidationHandler() // priority: 100
496
+ );
497
+
498
+ // Executes in priority order: Validation → Process
499
+ const results = await resolver.handleAllAsync('order', { id: 123, amount: 1000 });
500
+ // Results: [true, 'Processed order 123']
501
+ ```
502
+
255
503
  ## Use Cases
256
504
 
257
- 1. **Command Pattern Implementation**: Handle different types of commands with specific handlers
258
- 2. **Format Conversion**: Convert data between different formats based on type
259
- 3. **Request Processing**: Process different types of requests with dedicated handlers
260
- 4. **Plugin System**: Implement a plugin system where different plugins handle specific types of operations
261
- 5. **Message Formatting**: Format different types of messages with specific formatters
262
- 6. **Graceful Degradation**: Use fallback handlers to provide default behavior for unknown types
263
- 7. **API Versioning**: Handle different API versions with fallback to backward-compatible behavior
264
- 8. **Feature Flags**: Implement feature flags with fallback to basic functionality
505
+ 1. **Webhook Fanout**: Process a single webhook event with multiple handlers (accounting, notifications, analytics)
506
+ 2. **Event-Driven Architecture**: Route events to multiple subscribers based on event type
507
+ 3. **Command Pattern Implementation**: Handle different types of commands with specific handlers
508
+ 4. **Validation Pipeline**: Execute validation, business logic, and logging in priority order
509
+ 5. **Async Workflows**: Coordinate multiple async operations (DB saves, API calls, file operations)
510
+ 6. **Plugin System**: Implement a plugin system where different plugins handle specific types of operations
511
+ 7. **Message Formatting**: Format different types of messages with specific formatters
512
+ 8. **Graceful Degradation**: Use fallback handlers to provide default behavior for unknown types
513
+ 9. **API Versioning**: Handle different API versions with fallback to backward-compatible behavior
514
+ 10. **LINE Bot / Discord Bot**: Route different message types to appropriate handlers
265
515
 
266
516
  ## Error Handling
267
517
 
268
518
  The resolver will throw errors in the following cases:
269
- - When no resolvers are registered: `"Unasigned resolve target."`
519
+ - When no resolvers are registered: `"Unassigned resolve target."`
270
520
  - When trying to resolve an unsupported type: `"Unsupported type: xxx"`
271
521
 
272
522
  ### Fallback Handler for Error Prevention
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";class l{updaters=[];fallbackHandler;constructor(...t){t.length>0&&this.set(t)}getArgs(t){return[...t]}set(t){this.updaters=t}setUpdaters(...t){this.set(this.getArgs(t))}addUpdater(t){return this.updaters.push(t),this}setFallbackHandler(t){return this.fallbackHandler=t,this}getPriority(t){const r=t;return typeof r.priority=="number"?r.priority:0}sortByPriority(t){return[...t].sort((r,e)=>{const s=this.getPriority(r);return this.getPriority(e)-s})}resolve(t){if(this.updaters.length<1)throw new Error("Unassigned resolve target.");const r=this.updaters.filter(n=>n.supports(t)),s=this.sortByPriority(r)[0];if(!s){if(this.fallbackHandler)return{supports:()=>!0,handle:this.fallbackHandler};const n=typeof t=="object"&&t!==null?JSON.stringify(t):String(t);throw new Error(`Unsupported type: ${n}`)}return s}resolveAll(t){if(this.updaters.length<1)throw new Error("Unassigned resolve target.");const r=this.updaters.filter(e=>e.supports(t));return r.length===0?this.fallbackHandler?[{supports:()=>!0,handle:this.fallbackHandler}]:[]:this.sortByPriority(r)}handleAll(t,...r){return this.resolveAll(t).map(s=>s.handle(...r))}async handleAllAsync(t,...r){const s=this.resolveAll(t).map(n=>n.handle(...r));return Promise.all(s)}async handleAllSequential(t,...r){const e=this.resolveAll(t),s=[];for(const n of e){const i=await n.handle(...r);s.push(i)}return s}}module.exports=l;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../libs/resolver.ts"],"sourcesContent":["import type { ResolveTarget } from './interface';\n\n/**\n * Resolver class implementing the Chain of Responsibility pattern\n * Resolves handlers for specific types\n */\nclass Resolver<\n TBase extends ResolveTarget<any[], any, any> = ResolveTarget<any[], any, any>,\n TType = string,\n> {\n /**\n * Array of registered resolver targets\n * @private\n */\n private updaters: TBase[] = [];\n\n /**\n * Fallback handler function\n * @private\n */\n private fallbackHandler?: (...args: Parameters<TBase['handle']>) => ReturnType<TBase['handle']>;\n\n /**\n * Initializes the resolver\n * @param args Initial resolver targets\n */\n constructor(...args: TBase[]) {\n if (args.length > 0) {\n this.set(args);\n }\n }\n\n /**\n * Processes an array of arguments\n * @param args Array of resolver targets\n * @returns Processed array\n * @private\n */\n private getArgs(args: TBase[]): TBase[] {\n return [...args];\n }\n\n /**\n * Sets resolver targets\n * @param updaters Array of resolver targets\n */\n public set(updaters: TBase[]): void {\n this.updaters = updaters;\n }\n\n /**\n * Sets resolver targets (variadic version)\n * @param args Resolver targets\n */\n public setUpdaters(...args: TBase[]): void {\n this.set(this.getArgs(args));\n }\n\n /**\n * Adds a resolver target\n * @param updater Resolver target to add\n */\n public addUpdater(updater: TBase): this {\n this.updaters.push(updater);\n return this;\n }\n\n /**\n * Sets a fallback handler for unsupported types\n * @param handler Fallback handler function\n * @returns This resolver instance for method chaining\n */\n public setFallbackHandler(\n handler: (...args: Parameters<TBase['handle']>) => ReturnType<TBase['handle']>\n ): this {\n this.fallbackHandler = handler;\n return this;\n }\n\n /**\n * Gets the priority of a handler\n * @param handler The handler to get priority for\n * @returns Priority value (0 if not defined)\n * @private\n */\n private getPriority(handler: TBase): number {\n const handlerWithPriority = handler as Partial<{ priority: number }>;\n return typeof handlerWithPriority.priority === 'number' ? handlerWithPriority.priority : 0;\n }\n\n /**\n * Sorts handlers by priority (highest first), maintaining registration order for equal priorities\n * @param handlers Array of handlers to sort\n * @returns Sorted array of handlers\n * @private\n */\n private sortByPriority(handlers: TBase[]): TBase[] {\n return [...handlers].sort((a, b) => {\n const priorityA = this.getPriority(a);\n const priorityB = this.getPriority(b);\n return priorityB - priorityA; // Higher priority first\n });\n }\n\n /**\n * Resolves a resolver target for the specified type\n * @param type Type to resolve\n * @returns Resolved resolver target\n * @throws {Error} When no resolver targets are registered\n * @throws {Error} When no resolver target supporting the specified type is found and no fallback is set\n */\n public resolve(type: TType): TBase {\n if (this.updaters.length < 1) {\n throw new Error('Unassigned resolve target.');\n }\n\n // Get all matching handlers and sort by priority\n const matchingHandlers = this.updaters.filter((updater) => updater.supports(type));\n const sortedHandlers = this.sortByPriority(matchingHandlers);\n const target = sortedHandlers[0];\n\n if (!target) {\n // If fallback handler is set, create a temporary target that uses it\n if (this.fallbackHandler) {\n return {\n supports: () => true,\n handle: this.fallbackHandler,\n } as unknown as TBase;\n }\n\n // Determine the string representation of the unsupported type\n // If it's a non-null object, use JSON.stringify for detailed output\n // Otherwise, use String() for basic conversion\n const typeString =\n typeof type === 'object' && type !== null ? JSON.stringify(type) : String(type);\n throw new Error(`Unsupported type: ${typeString}`);\n }\n\n return target;\n }\n\n /**\n * Resolves all resolver targets for the specified type\n * @param type Type to resolve\n * @returns Array of all matching resolver targets sorted by priority (highest first).\n * Returns an empty array if no handlers match and no fallback is set.\n * Note: Unlike resolve(), this method does not throw when no handlers match.\n * @throws {Error} When no resolver targets are registered\n */\n public resolveAll(type: TType): TBase[] {\n if (this.updaters.length < 1) {\n throw new Error('Unassigned resolve target.');\n }\n\n const targets = this.updaters.filter((updater) => updater.supports(type));\n\n if (targets.length === 0) {\n // If fallback handler is set, return it as a single-element array\n if (this.fallbackHandler) {\n return [\n {\n supports: () => true,\n handle: this.fallbackHandler,\n } as unknown as TBase,\n ];\n }\n\n // Return empty array if no handlers match\n return [];\n }\n\n // Sort by priority (highest first)\n return this.sortByPriority(targets);\n }\n\n /**\n * Executes all matching handlers for the specified type\n * @param type Type to resolve\n * @param args Arguments to pass to the handlers\n * @returns Array of results from all matching handlers\n * @throws {Error} When no resolver targets are registered\n */\n public handleAll(\n type: TType,\n ...args: Parameters<TBase['handle']>\n ): ReturnType<TBase['handle']>[] {\n const targets = this.resolveAll(type);\n return targets.map((target) => target.handle(...args));\n }\n\n /**\n * Executes all matching async handlers in parallel for the specified type\n * @param type Type to resolve\n * @param args Arguments to pass to the handlers\n * @returns Promise that resolves to array of results from all matching handlers\n * @throws {Error} When no resolver targets are registered\n */\n public async handleAllAsync(\n type: TType,\n ...args: Parameters<TBase['handle']>\n ): Promise<Awaited<ReturnType<TBase['handle']>>[]> {\n const targets = this.resolveAll(type);\n const promises = targets.map((target) => target.handle(...args));\n return Promise.all(promises);\n }\n\n /**\n * Executes all matching async handlers sequentially for the specified type\n * Stops on first error\n * @param type Type to resolve\n * @param args Arguments to pass to the handlers\n * @returns Promise that resolves to array of results from all matching handlers\n * @throws {Error} When no resolver targets are registered\n * @throws {Error} When any handler throws an error\n */\n public async handleAllSequential(\n type: TType,\n ...args: Parameters<TBase['handle']>\n ): Promise<Awaited<ReturnType<TBase['handle']>>[]> {\n const targets = this.resolveAll(type);\n const results: Awaited<ReturnType<TBase['handle']>>[] = [];\n\n for (const target of targets) {\n const result = await target.handle(...args);\n results.push(result);\n }\n\n return results;\n }\n}\n\nexport default Resolver;\n"],"names":["Resolver","args","updaters","updater","handler","handlerWithPriority","handlers","a","b","priorityA","type","matchingHandlers","target","typeString","targets","promises","results","result"],"mappings":"aAMA,MAAMA,CAGJ,CAKQ,SAAoB,CAAA,EAMpB,gBAMR,eAAeC,EAAe,CACxBA,EAAK,OAAS,GAChB,KAAK,IAAIA,CAAI,CAEjB,CAQQ,QAAQA,EAAwB,CACtC,MAAO,CAAC,GAAGA,CAAI,CACjB,CAMO,IAAIC,EAAyB,CAClC,KAAK,SAAWA,CAClB,CAMO,eAAeD,EAAqB,CACzC,KAAK,IAAI,KAAK,QAAQA,CAAI,CAAC,CAC7B,CAMO,WAAWE,EAAsB,CACtC,YAAK,SAAS,KAAKA,CAAO,EACnB,IACT,CAOO,mBACLC,EACM,CACN,YAAK,gBAAkBA,EAChB,IACT,CAQQ,YAAYA,EAAwB,CAC1C,MAAMC,EAAsBD,EAC5B,OAAO,OAAOC,EAAoB,UAAa,SAAWA,EAAoB,SAAW,CAC3F,CAQQ,eAAeC,EAA4B,CACjD,MAAO,CAAC,GAAGA,CAAQ,EAAE,KAAK,CAACC,EAAGC,IAAM,CAClC,MAAMC,EAAY,KAAK,YAAYF,CAAC,EAEpC,OADkB,KAAK,YAAYC,CAAC,EACjBC,CACrB,CAAC,CACH,CASO,QAAQC,EAAoB,CACjC,GAAI,KAAK,SAAS,OAAS,EACzB,MAAM,IAAI,MAAM,4BAA4B,EAI9C,MAAMC,EAAmB,KAAK,SAAS,OAAQR,GAAYA,EAAQ,SAASO,CAAI,CAAC,EAE3EE,EADiB,KAAK,eAAeD,CAAgB,EAC7B,CAAC,EAE/B,GAAI,CAACC,EAAQ,CAEX,GAAI,KAAK,gBACP,MAAO,CACL,SAAU,IAAM,GAChB,OAAQ,KAAK,eAAA,EAOjB,MAAMC,EACJ,OAAOH,GAAS,UAAYA,IAAS,KAAO,KAAK,UAAUA,CAAI,EAAI,OAAOA,CAAI,EAChF,MAAM,IAAI,MAAM,qBAAqBG,CAAU,EAAE,CACnD,CAEA,OAAOD,CACT,CAUO,WAAWF,EAAsB,CACtC,GAAI,KAAK,SAAS,OAAS,EACzB,MAAM,IAAI,MAAM,4BAA4B,EAG9C,MAAMI,EAAU,KAAK,SAAS,OAAQX,GAAYA,EAAQ,SAASO,CAAI,CAAC,EAExE,OAAII,EAAQ,SAAW,EAEjB,KAAK,gBACA,CACL,CACE,SAAU,IAAM,GAChB,OAAQ,KAAK,eAAA,CACf,EAKG,CAAA,EAIF,KAAK,eAAeA,CAAO,CACpC,CASO,UACLJ,KACGT,EAC4B,CAE/B,OADgB,KAAK,WAAWS,CAAI,EACrB,IAAKE,GAAWA,EAAO,OAAO,GAAGX,CAAI,CAAC,CACvD,CASA,MAAa,eACXS,KACGT,EAC8C,CAEjD,MAAMc,EADU,KAAK,WAAWL,CAAI,EACX,IAAKE,GAAWA,EAAO,OAAO,GAAGX,CAAI,CAAC,EAC/D,OAAO,QAAQ,IAAIc,CAAQ,CAC7B,CAWA,MAAa,oBACXL,KACGT,EAC8C,CACjD,MAAMa,EAAU,KAAK,WAAWJ,CAAI,EAC9BM,EAAkD,CAAA,EAExD,UAAWJ,KAAUE,EAAS,CAC5B,MAAMG,EAAS,MAAML,EAAO,OAAO,GAAGX,CAAI,EAC1Ce,EAAQ,KAAKC,CAAM,CACrB,CAEA,OAAOD,CACT,CACF"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,190 @@
1
- export * from './interface';
2
- import Resolver from './resolver';
3
- export default Resolver;
1
+ /**
2
+ * Interface for async resolver targets
3
+ * Handle method returns a Promise
4
+ */
5
+ export declare interface AsyncResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> extends SupportsType<TType> {
6
+ /**
7
+ * Handles the request asynchronously
8
+ * @param args Arguments needed for processing
9
+ * @returns Promise with processing result
10
+ */
11
+ handle(...args: TArgs): Promise<TReturn>;
12
+ }
13
+
14
+ /**
15
+ * Interface for prioritized handlers
16
+ * Higher priority values are executed first
17
+ */
18
+ export declare interface HasPriority {
19
+ /**
20
+ * Priority for this handler (higher values execute first)
21
+ * Default is 0 if not specified
22
+ */
23
+ priority?: number;
24
+ }
25
+
26
+ export declare namespace interfaces {
27
+ export interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
28
+ supports(type: TType): boolean;
29
+ handle(...args: TArgs): TReturn;
30
+ }
31
+ export interface PrioritizedResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> extends ResolveTarget<TArgs, TReturn, TType> {
32
+ priority?: number;
33
+ }
34
+ export interface AsyncResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> {
35
+ supports(type: TType): boolean;
36
+ handle(...args: TArgs): Promise<TReturn>;
37
+ }
38
+ export interface PrioritizedAsyncResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> extends AsyncResolveTarget<TArgs, TReturn, TType> {
39
+ priority?: number;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Interface for async resolver targets with priority support
45
+ * Higher priority values are executed first
46
+ */
47
+ export declare interface PrioritizedAsyncResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> extends AsyncResolveTarget<TArgs, TReturn, TType>, HasPriority {
48
+ }
49
+
50
+ /**
51
+ * Interface for resolver targets with priority support
52
+ * Higher priority values are executed first
53
+ */
54
+ export declare interface PrioritizedResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> extends ResolveTarget<TArgs, TReturn, TType>, HasPriority {
55
+ }
56
+
57
+ /**
58
+ * Resolver class implementing the Chain of Responsibility pattern
59
+ * Resolves handlers for specific types
60
+ */
61
+ declare class Resolver<TBase extends ResolveTarget<any[], any, any> = ResolveTarget<any[], any, any>, TType = string> {
62
+ /**
63
+ * Array of registered resolver targets
64
+ * @private
65
+ */
66
+ private updaters;
67
+ /**
68
+ * Fallback handler function
69
+ * @private
70
+ */
71
+ private fallbackHandler?;
72
+ /**
73
+ * Initializes the resolver
74
+ * @param args Initial resolver targets
75
+ */
76
+ constructor(...args: TBase[]);
77
+ /**
78
+ * Processes an array of arguments
79
+ * @param args Array of resolver targets
80
+ * @returns Processed array
81
+ * @private
82
+ */
83
+ private getArgs;
84
+ /**
85
+ * Sets resolver targets
86
+ * @param updaters Array of resolver targets
87
+ */
88
+ set(updaters: TBase[]): void;
89
+ /**
90
+ * Sets resolver targets (variadic version)
91
+ * @param args Resolver targets
92
+ */
93
+ setUpdaters(...args: TBase[]): void;
94
+ /**
95
+ * Adds a resolver target
96
+ * @param updater Resolver target to add
97
+ */
98
+ addUpdater(updater: TBase): this;
99
+ /**
100
+ * Sets a fallback handler for unsupported types
101
+ * @param handler Fallback handler function
102
+ * @returns This resolver instance for method chaining
103
+ */
104
+ setFallbackHandler(handler: (...args: Parameters<TBase['handle']>) => ReturnType<TBase['handle']>): this;
105
+ /**
106
+ * Gets the priority of a handler
107
+ * @param handler The handler to get priority for
108
+ * @returns Priority value (0 if not defined)
109
+ * @private
110
+ */
111
+ private getPriority;
112
+ /**
113
+ * Sorts handlers by priority (highest first), maintaining registration order for equal priorities
114
+ * @param handlers Array of handlers to sort
115
+ * @returns Sorted array of handlers
116
+ * @private
117
+ */
118
+ private sortByPriority;
119
+ /**
120
+ * Resolves a resolver target for the specified type
121
+ * @param type Type to resolve
122
+ * @returns Resolved resolver target
123
+ * @throws {Error} When no resolver targets are registered
124
+ * @throws {Error} When no resolver target supporting the specified type is found and no fallback is set
125
+ */
126
+ resolve(type: TType): TBase;
127
+ /**
128
+ * Resolves all resolver targets for the specified type
129
+ * @param type Type to resolve
130
+ * @returns Array of all matching resolver targets sorted by priority (highest first).
131
+ * Returns an empty array if no handlers match and no fallback is set.
132
+ * Note: Unlike resolve(), this method does not throw when no handlers match.
133
+ * @throws {Error} When no resolver targets are registered
134
+ */
135
+ resolveAll(type: TType): TBase[];
136
+ /**
137
+ * Executes all matching handlers for the specified type
138
+ * @param type Type to resolve
139
+ * @param args Arguments to pass to the handlers
140
+ * @returns Array of results from all matching handlers
141
+ * @throws {Error} When no resolver targets are registered
142
+ */
143
+ handleAll(type: TType, ...args: Parameters<TBase['handle']>): ReturnType<TBase['handle']>[];
144
+ /**
145
+ * Executes all matching async handlers in parallel for the specified type
146
+ * @param type Type to resolve
147
+ * @param args Arguments to pass to the handlers
148
+ * @returns Promise that resolves to array of results from all matching handlers
149
+ * @throws {Error} When no resolver targets are registered
150
+ */
151
+ handleAllAsync(type: TType, ...args: Parameters<TBase['handle']>): Promise<Awaited<ReturnType<TBase['handle']>>[]>;
152
+ /**
153
+ * Executes all matching async handlers sequentially for the specified type
154
+ * Stops on first error
155
+ * @param type Type to resolve
156
+ * @param args Arguments to pass to the handlers
157
+ * @returns Promise that resolves to array of results from all matching handlers
158
+ * @throws {Error} When no resolver targets are registered
159
+ * @throws {Error} When any handler throws an error
160
+ */
161
+ handleAllSequential(type: TType, ...args: Parameters<TBase['handle']>): Promise<Awaited<ReturnType<TBase['handle']>>[]>;
162
+ }
163
+ export default Resolver;
164
+
165
+ /**
166
+ * Interface that classes which are targets for the resolver should implement
167
+ */
168
+ export declare interface ResolveTarget<TArgs extends any[] = any[], TReturn = any, TType = string> extends SupportsType<TType> {
169
+ /**
170
+ * Handles the request
171
+ * @param args Arguments needed for processing
172
+ * @returns Processing result
173
+ */
174
+ handle(...args: TArgs): TReturn;
175
+ }
176
+
177
+ /**
178
+ * Base interface for type matching
179
+ * Extracted to reduce code duplication across sync and async targets
180
+ */
181
+ export declare interface SupportsType<TType = string> {
182
+ /**
183
+ * Determines whether the specified type is supported
184
+ * @param type The type to check for support
185
+ * @returns true if supported, false otherwise
186
+ */
187
+ supports(type: TType): boolean;
188
+ }
189
+
190
+ export { }
package/dist/index.mjs ADDED
@@ -0,0 +1,162 @@
1
+ class a {
2
+ /**
3
+ * Array of registered resolver targets
4
+ * @private
5
+ */
6
+ updaters = [];
7
+ /**
8
+ * Fallback handler function
9
+ * @private
10
+ */
11
+ fallbackHandler;
12
+ /**
13
+ * Initializes the resolver
14
+ * @param args Initial resolver targets
15
+ */
16
+ constructor(...t) {
17
+ t.length > 0 && this.set(t);
18
+ }
19
+ /**
20
+ * Processes an array of arguments
21
+ * @param args Array of resolver targets
22
+ * @returns Processed array
23
+ * @private
24
+ */
25
+ getArgs(t) {
26
+ return [...t];
27
+ }
28
+ /**
29
+ * Sets resolver targets
30
+ * @param updaters Array of resolver targets
31
+ */
32
+ set(t) {
33
+ this.updaters = t;
34
+ }
35
+ /**
36
+ * Sets resolver targets (variadic version)
37
+ * @param args Resolver targets
38
+ */
39
+ setUpdaters(...t) {
40
+ this.set(this.getArgs(t));
41
+ }
42
+ /**
43
+ * Adds a resolver target
44
+ * @param updater Resolver target to add
45
+ */
46
+ addUpdater(t) {
47
+ return this.updaters.push(t), this;
48
+ }
49
+ /**
50
+ * Sets a fallback handler for unsupported types
51
+ * @param handler Fallback handler function
52
+ * @returns This resolver instance for method chaining
53
+ */
54
+ setFallbackHandler(t) {
55
+ return this.fallbackHandler = t, this;
56
+ }
57
+ /**
58
+ * Gets the priority of a handler
59
+ * @param handler The handler to get priority for
60
+ * @returns Priority value (0 if not defined)
61
+ * @private
62
+ */
63
+ getPriority(t) {
64
+ const r = t;
65
+ return typeof r.priority == "number" ? r.priority : 0;
66
+ }
67
+ /**
68
+ * Sorts handlers by priority (highest first), maintaining registration order for equal priorities
69
+ * @param handlers Array of handlers to sort
70
+ * @returns Sorted array of handlers
71
+ * @private
72
+ */
73
+ sortByPriority(t) {
74
+ return [...t].sort((r, s) => {
75
+ const e = this.getPriority(r);
76
+ return this.getPriority(s) - e;
77
+ });
78
+ }
79
+ /**
80
+ * Resolves a resolver target for the specified type
81
+ * @param type Type to resolve
82
+ * @returns Resolved resolver target
83
+ * @throws {Error} When no resolver targets are registered
84
+ * @throws {Error} When no resolver target supporting the specified type is found and no fallback is set
85
+ */
86
+ resolve(t) {
87
+ if (this.updaters.length < 1)
88
+ throw new Error("Unassigned resolve target.");
89
+ const r = this.updaters.filter((n) => n.supports(t)), e = this.sortByPriority(r)[0];
90
+ if (!e) {
91
+ if (this.fallbackHandler)
92
+ return {
93
+ supports: () => !0,
94
+ handle: this.fallbackHandler
95
+ };
96
+ const n = typeof t == "object" && t !== null ? JSON.stringify(t) : String(t);
97
+ throw new Error(`Unsupported type: ${n}`);
98
+ }
99
+ return e;
100
+ }
101
+ /**
102
+ * Resolves all resolver targets for the specified type
103
+ * @param type Type to resolve
104
+ * @returns Array of all matching resolver targets sorted by priority (highest first).
105
+ * Returns an empty array if no handlers match and no fallback is set.
106
+ * Note: Unlike resolve(), this method does not throw when no handlers match.
107
+ * @throws {Error} When no resolver targets are registered
108
+ */
109
+ resolveAll(t) {
110
+ if (this.updaters.length < 1)
111
+ throw new Error("Unassigned resolve target.");
112
+ const r = this.updaters.filter((s) => s.supports(t));
113
+ return r.length === 0 ? this.fallbackHandler ? [
114
+ {
115
+ supports: () => !0,
116
+ handle: this.fallbackHandler
117
+ }
118
+ ] : [] : this.sortByPriority(r);
119
+ }
120
+ /**
121
+ * Executes all matching handlers for the specified type
122
+ * @param type Type to resolve
123
+ * @param args Arguments to pass to the handlers
124
+ * @returns Array of results from all matching handlers
125
+ * @throws {Error} When no resolver targets are registered
126
+ */
127
+ handleAll(t, ...r) {
128
+ return this.resolveAll(t).map((e) => e.handle(...r));
129
+ }
130
+ /**
131
+ * Executes all matching async handlers in parallel for the specified type
132
+ * @param type Type to resolve
133
+ * @param args Arguments to pass to the handlers
134
+ * @returns Promise that resolves to array of results from all matching handlers
135
+ * @throws {Error} When no resolver targets are registered
136
+ */
137
+ async handleAllAsync(t, ...r) {
138
+ const e = this.resolveAll(t).map((n) => n.handle(...r));
139
+ return Promise.all(e);
140
+ }
141
+ /**
142
+ * Executes all matching async handlers sequentially for the specified type
143
+ * Stops on first error
144
+ * @param type Type to resolve
145
+ * @param args Arguments to pass to the handlers
146
+ * @returns Promise that resolves to array of results from all matching handlers
147
+ * @throws {Error} When no resolver targets are registered
148
+ * @throws {Error} When any handler throws an error
149
+ */
150
+ async handleAllSequential(t, ...r) {
151
+ const s = this.resolveAll(t), e = [];
152
+ for (const n of s) {
153
+ const l = await n.handle(...r);
154
+ e.push(l);
155
+ }
156
+ return e;
157
+ }
158
+ }
159
+ export {
160
+ a as default
161
+ };
162
+ //# sourceMappingURL=index.mjs.map