@oldzy/conduit 1.0.1 → 1.0.3

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
@@ -4,12 +4,13 @@ Transport-agnostic request/response pipeline framework with mediator pattern, de
4
4
 
5
5
  ## Features
6
6
 
7
- - 🎯 Mediator pattern for clean request/response handling
8
- - 💉 Built-in dependency injection
9
- - 🔧 Flexible middleware pipeline
10
- - 🚀 Transport-agnostic architecture
11
- - 📦 TypeScript support with full type safety
12
- - Lightweight and performant
7
+ - 🎯 **Mediator Pattern** - Clean request/response handling with type-safe handlers
8
+ - 💉 **Dependency Injection** - Built-in DI container with three lifetime scopes (Singleton, Scoped, Transient)
9
+ - 🔧 **Pipeline Behaviors** - Middleware support for cross-cutting concerns (logging, validation, error handling)
10
+ - 🚀 **Transport-Agnostic** - Adapter pattern for any transport (HTTP, IPC, WebSocket, etc.)
11
+ - 📡 **Streaming Support** - Built-in support for both simple and streaming responses
12
+ - 📦 **TypeScript First** - Full type safety with generics
13
+ - ⚡ **Lightweight** - Zero dependencies (except uuid and reflect-metadata)
13
14
 
14
15
  ## Installation
15
16
 
@@ -17,6 +18,708 @@ Transport-agnostic request/response pipeline framework with mediator pattern, de
17
18
  npm install @oldzy/conduit
18
19
  ```
19
20
 
21
+ ## Quick Start
22
+
23
+ ```typescript
24
+ import { ApplicationBuilder, BaseRequest, BaseResponse, SimpleHandler } from '@oldzy/conduit';
25
+
26
+ // 1. Define your request
27
+ class GetUserRequest extends BaseRequest {
28
+ constructor(public userId: string) {
29
+ super('GET_USER');
30
+ }
31
+ }
32
+
33
+ // 2. Define your response
34
+ class GetUserResponse extends BaseResponse {
35
+ constructor(public userName: string, public email: string) {
36
+ super('GET_USER_RESPONSE');
37
+ }
38
+ }
39
+
40
+ // 3. Create a handler
41
+ class GetUserHandler extends SimpleHandler<GetUserRequest, GetUserResponse> {
42
+ protected async handleSimple(request: GetUserRequest): Promise<GetUserResponse> {
43
+ // Your business logic here
44
+ return new GetUserResponse(`User ${request.userId}`, 'user@example.com');
45
+ }
46
+ }
47
+
48
+ // 4. Build and run the application
49
+ const app = await new ApplicationBuilder()
50
+ .registerHandler('GET_USER', GetUserHandler)
51
+ .build();
52
+
53
+ await app.run();
54
+
55
+ // 5. Send requests
56
+ const request = new GetUserRequest('123');
57
+ const response = await app.send<GetUserResponse>(request);
58
+
59
+ console.log(response.userName); // "User 123"
60
+ ```
61
+
62
+ ## Core Concepts
63
+
64
+ ### Requests and Responses
65
+
66
+ All requests must extend `BaseRequest` and all responses must extend `BaseResponse`.
67
+
68
+ ```typescript
69
+ // Request with auto-generated UUID and timestamp
70
+ class CreateOrderRequest extends BaseRequest {
71
+ constructor(
72
+ public productId: string,
73
+ public quantity: number
74
+ ) {
75
+ super('CREATE_ORDER'); // Request type identifier
76
+ }
77
+ }
78
+
79
+ // Response with success/error handling
80
+ class CreateOrderResponse extends BaseResponse {
81
+ constructor(public orderId: string, public total: number) {
82
+ super('CREATE_ORDER_RESPONSE');
83
+ }
84
+ }
85
+ ```
86
+
87
+ **BaseRequest** includes:
88
+ - `uuid`: Auto-generated unique identifier
89
+ - `timestamp`: Request creation time
90
+ - `type`: Request type identifier
91
+
92
+ **BaseResponse** includes:
93
+ - `success`: Boolean indicating success/failure
94
+ - `errors`: Optional array of error messages
95
+ - `timestamp`: Response creation time
96
+ - `addError(error)`: Helper to add errors
97
+ - `setErrors(errors)`: Helper to set multiple errors
98
+
99
+ ### Handlers
100
+
101
+ Conduit provides two types of handlers:
102
+
103
+ #### Simple Handlers
104
+
105
+ For single-response requests:
106
+
107
+ ```typescript
108
+ class GetUserHandler extends SimpleHandler<GetUserRequest, GetUserResponse> {
109
+ protected async handleSimple(request: GetUserRequest): Promise<GetUserResponse> {
110
+ const user = await database.getUser(request.userId);
111
+ return new GetUserResponse(user.name, user.email);
112
+ }
113
+ }
114
+ ```
115
+
116
+ #### Streaming Handlers
117
+
118
+ For streaming/chunked responses:
119
+
120
+ ```typescript
121
+ class StreamLogsRequest extends BaseRequest {
122
+ constructor(public filename: string) {
123
+ super('STREAM_LOGS');
124
+ }
125
+ }
126
+
127
+ class LogChunkResponse extends BaseResponse {
128
+ constructor(public line: string) {
129
+ super('LOG_CHUNK');
130
+ }
131
+ }
132
+
133
+ class StreamLogsHandler extends StreamingHandler<StreamLogsRequest, LogChunkResponse> {
134
+ protected async handleStream(request: StreamLogsRequest): Promise<AsyncIterable<LogChunkResponse>> {
135
+ return {
136
+ async *[Symbol.asyncIterator]() {
137
+ const lines = await readFileLines(request.filename);
138
+ for (const line of lines) {
139
+ yield new LogChunkResponse(line);
140
+ }
141
+ }
142
+ };
143
+ }
144
+ }
145
+ ```
146
+
147
+ ### Sending Requests
148
+
149
+ Use the appropriate method based on your handler type:
150
+
151
+ ```typescript
152
+ // For simple handlers - returns a single response
153
+ const response = await app.send<GetUserResponse>(request);
154
+
155
+ // For streaming handlers - returns an async iterable
156
+ const stream = await app.stream<LogChunkResponse>(request);
157
+ for await (const chunk of stream) {
158
+ console.log(chunk.line);
159
+ }
160
+ ```
161
+
162
+ **Important**: Using `send()` with a streaming handler or `stream()` with a simple handler will throw an error.
163
+
164
+ ### Dependency Injection
165
+
166
+ Conduit includes a full-featured DI container with three lifetime scopes:
167
+
168
+ #### Service Lifetimes
169
+
170
+ - **Singleton**: Created once and shared across the entire application lifetime
171
+ - **Scoped**: Created once per request (each `send()` or `stream()` call gets a new instance)
172
+ - **Transient**: Created every time the service is requested
173
+
174
+ **Important**: Conduit automatically creates a new scope for each request, making Scoped services perfect for:
175
+ - Database transactions (commit/rollback per request)
176
+ - Request-specific caching
177
+ - Request context and metadata
178
+ - Per-request logging with correlation IDs
179
+
180
+ ```typescript
181
+ class UserRepository {
182
+ async getUser(id: string) {
183
+ return { id, name: 'John Doe' };
184
+ }
185
+ }
186
+
187
+ class Logger {
188
+ log(message: string) {
189
+ console.log(`[${new Date().toISOString()}] ${message}`);
190
+ }
191
+ }
192
+
193
+ const app = await new ApplicationBuilder()
194
+ // Register services
195
+ .registerSingleton('UserRepository', UserRepository)
196
+ .registerTransient('Logger', Logger)
197
+
198
+ // Register handler with dependency injection
199
+ .registerFactory('GET_USER', (provider) => {
200
+ const repo = provider.getRequiredService<UserRepository>('UserRepository');
201
+ const logger = provider.getRequiredService<Logger>('Logger');
202
+ return new GetUserHandler(repo, logger);
203
+ })
204
+ .build();
205
+ ```
206
+
207
+ #### Scoped Services Example
208
+
209
+ Scoped services are perfect for per-request state. Each `send()` or `stream()` call creates a new scope:
210
+
211
+ ```typescript
212
+ // Database transaction that lives for the duration of a request
213
+ class DatabaseTransaction {
214
+ private isCommitted = false;
215
+ private isRolledBack = false;
216
+
217
+ async execute(query: string) {
218
+ if (this.isCommitted || this.isRolledBack) {
219
+ throw new Error('Transaction already completed');
220
+ }
221
+ // Execute query within transaction
222
+ }
223
+
224
+ async commit() {
225
+ this.isCommitted = true;
226
+ // Commit transaction
227
+ }
228
+
229
+ async rollback() {
230
+ this.isRolledBack = true;
231
+ // Rollback transaction
232
+ }
233
+ }
234
+
235
+ // Request cache that's cleared after each request
236
+ class RequestCache {
237
+ private cache = new Map<string, any>();
238
+
239
+ get<T>(key: string): T | undefined {
240
+ return this.cache.get(key);
241
+ }
242
+
243
+ set<T>(key: string, value: T): void {
244
+ this.cache.set(key, value);
245
+ }
246
+ }
247
+
248
+ // Handler using scoped services
249
+ class CreateOrderHandler extends SimpleHandler<CreateOrderRequest, CreateOrderResponse> {
250
+ constructor(
251
+ private transaction: DatabaseTransaction,
252
+ private cache: RequestCache
253
+ ) {
254
+ super();
255
+ }
256
+
257
+ protected async handleSimple(request: CreateOrderRequest): Promise<CreateOrderResponse> {
258
+ try {
259
+ // Check cache first
260
+ const cached = this.cache.get('product:' + request.productId);
261
+
262
+ // Use transaction
263
+ await this.transaction.execute('INSERT INTO orders...');
264
+ await this.transaction.execute('UPDATE inventory...');
265
+
266
+ // Commit transaction
267
+ await this.transaction.commit();
268
+
269
+ return new CreateOrderResponse('order-123');
270
+ } catch (error) {
271
+ // Rollback on error
272
+ await this.transaction.rollback();
273
+ throw error;
274
+ }
275
+ }
276
+ }
277
+
278
+ const app = await new ApplicationBuilder()
279
+ // Scoped services - new instance per request
280
+ .registerScoped('DatabaseTransaction', DatabaseTransaction)
281
+ .registerScoped('RequestCache', RequestCache)
282
+
283
+ // Handler factory
284
+ .registerFactory('CREATE_ORDER', (provider) => {
285
+ const transaction = provider.getRequiredService<DatabaseTransaction>('DatabaseTransaction');
286
+ const cache = provider.getRequiredService<RequestCache>('RequestCache');
287
+ return new CreateOrderHandler(transaction, cache);
288
+ })
289
+ .build();
290
+
291
+ await app.run();
292
+
293
+ // Each request gets its own transaction and cache
294
+ const order1 = await app.send(new CreateOrderRequest('product-1'));
295
+ const order2 = await app.send(new CreateOrderRequest('product-2'));
296
+ // order1 and order2 had separate DatabaseTransaction instances
297
+ ```
298
+
299
+ #### Using @Inject Decorator
300
+
301
+ ```typescript
302
+ import { Inject } from '@oldzy/conduit/di';
303
+
304
+ class GetUserHandler extends SimpleHandler<GetUserRequest, GetUserResponse> {
305
+ constructor(
306
+ @Inject('UserRepository') private repository: UserRepository,
307
+ @Inject('Logger') private logger: Logger
308
+ ) {
309
+ super();
310
+ }
311
+
312
+ protected async handleSimple(request: GetUserRequest): Promise<GetUserResponse> {
313
+ this.logger.log(`Fetching user ${request.userId}`);
314
+ const user = await this.repository.getUser(request.userId);
315
+ return new GetUserResponse(user.name, user.email);
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### Pipeline Behaviors (Middleware)
321
+
322
+ Behaviors allow you to add cross-cutting concerns like logging, validation, and error handling:
323
+
324
+ ```typescript
325
+ class LoggingBehavior implements IPipelineBehavior {
326
+ async handle(context: PipelineContext, next: PipelineDelegate): HandlerResult<BaseResponse> {
327
+ console.log(`Handling: ${context.request.type}`);
328
+ const startTime = Date.now();
329
+
330
+ const response = await next();
331
+
332
+ const duration = Date.now() - startTime;
333
+ console.log(`Completed in ${duration}ms`);
334
+
335
+ return response;
336
+ }
337
+ }
338
+
339
+ class ErrorHandlingBehavior implements IPipelineBehavior {
340
+ async handle(context: PipelineContext, next: PipelineDelegate): HandlerResult<BaseResponse> {
341
+ try {
342
+ return await next();
343
+ } catch (error) {
344
+ const response = new BaseResponse('ERROR_RESPONSE');
345
+ response.addError(error instanceof Error ? error.message : 'Unknown error');
346
+ return response;
347
+ }
348
+ }
349
+ }
350
+
351
+ const app = await new ApplicationBuilder()
352
+ .registerHandler('GET_USER', GetUserHandler)
353
+ .registerBehavior(new LoggingBehavior())
354
+ .registerBehavior(new ErrorHandlingBehavior())
355
+ .build();
356
+ ```
357
+
358
+ **Execution Order**: Behaviors are executed in the order they are registered:
359
+ ```
360
+ LoggingBehavior (before) → ErrorHandlingBehavior (before) → Handler → ErrorHandlingBehavior (after) → LoggingBehavior (after)
361
+ ```
362
+
363
+ ### Transport Adapters
364
+
365
+ Adapters connect your application to specific transports (HTTP, IPC, WebSocket, etc.):
366
+
367
+ ```typescript
368
+ interface IApplicationAdapter {
369
+ readonly name: string;
370
+ configure(services: ServiceCollection): void | Promise<void>;
371
+ initialize?(app: Application): void | Promise<void>;
372
+ dispose?(): void | Promise<void>;
373
+ }
374
+ ```
375
+
376
+ #### Example: HTTP Adapter with Express
377
+
378
+ ```typescript
379
+ import express from 'express';
380
+
381
+ class ExpressAdapter implements IApplicationAdapter {
382
+ readonly name = 'express-adapter';
383
+ private server?: Server;
384
+
385
+ configure(services: ServiceCollection): void {
386
+ // Register transport-specific services
387
+ }
388
+
389
+ async initialize(app: Application): Promise<void> {
390
+ const expressApp = express();
391
+
392
+ expressApp.post('/api/:requestType', async (req, res) => {
393
+ const { requestType } = req.params;
394
+
395
+ // Create request from HTTP body
396
+ const request = this.createRequest(requestType, req.body);
397
+
398
+ try {
399
+ const response = await app.send(request);
400
+ res.json(response);
401
+ } catch (error) {
402
+ res.status(500).json({ error: error.message });
403
+ }
404
+ });
405
+
406
+ this.server = expressApp.listen(3000);
407
+ }
408
+
409
+ async dispose(): Promise<void> {
410
+ if (this.server) {
411
+ this.server.close();
412
+ }
413
+ }
414
+ }
415
+
416
+ const app = await new ApplicationBuilder()
417
+ .registerHandler('GET_USER', GetUserHandler)
418
+ .use(new ExpressAdapter())
419
+ .build();
420
+
421
+ await app.run();
422
+ ```
423
+
424
+ #### Example: Electron IPC Adapter with Streaming
425
+
426
+ ```typescript
427
+ import { ipcMain } from 'electron';
428
+
429
+ class ElectronAdapter implements IApplicationAdapter {
430
+ readonly name = 'electron-adapter';
431
+ private requestControllers = new Map<string, AbortController>();
432
+
433
+ configure(services: ServiceCollection): void {}
434
+
435
+ async initialize(app: Application): Promise<void> {
436
+ // Handle simple requests
437
+ ipcMain.handle('conduit:send', async (event, requestData) => {
438
+ const request = this.createRequest(requestData);
439
+ return await app.send(request);
440
+ });
441
+
442
+ // Handle streaming requests
443
+ ipcMain.handle('conduit:stream', async (event, requestData) => {
444
+ const request = this.createRequest(requestData);
445
+ const requestId = request.uuid;
446
+
447
+ const abortController = new AbortController();
448
+ this.requestControllers.set(requestId, abortController);
449
+
450
+ try {
451
+ const stream = await app.stream(request);
452
+
453
+ for await (const response of stream) {
454
+ if (abortController.signal.aborted) break;
455
+ event.sender.send(`conduit:stream:${requestId}`, response);
456
+ }
457
+
458
+ event.sender.send(`conduit:stream:${requestId}:complete`);
459
+ } catch (error) {
460
+ event.sender.send(`conduit:stream:${requestId}:error`, error.message);
461
+ } finally {
462
+ this.requestControllers.delete(requestId);
463
+ }
464
+ });
465
+
466
+ // Handle cancellation
467
+ ipcMain.on('conduit:cancel', (event, requestId) => {
468
+ const controller = this.requestControllers.get(requestId);
469
+ if (controller) {
470
+ controller.abort();
471
+ this.requestControllers.delete(requestId);
472
+ }
473
+ });
474
+ }
475
+
476
+ dispose(): void {
477
+ ipcMain.removeHandler('conduit:send');
478
+ ipcMain.removeHandler('conduit:stream');
479
+ ipcMain.removeAllListeners('conduit:cancel');
480
+ }
481
+ }
482
+ ```
483
+
484
+ ## Application Builder API
485
+
486
+ The `ApplicationBuilder` provides a fluent API for configuring your application:
487
+
488
+ ```typescript
489
+ const app = await new ApplicationBuilder()
490
+ // Register handlers
491
+ .registerHandler('REQUEST_TYPE', HandlerClass, ServiceLifetime.Transient)
492
+ .registerHandlers(handlersMap)
493
+
494
+ // Register services
495
+ .registerSingleton('ServiceName', ServiceClass)
496
+ .registerScoped('ServiceName', ServiceClass)
497
+ .registerTransient('ServiceName', ServiceClass)
498
+ .registerFactory('ServiceName', (provider) => new Service(...), ServiceLifetime.Singleton)
499
+
500
+ // Register behaviors (middleware)
501
+ .registerBehavior(new BehaviorInstance())
502
+ .registerBehavior(BehaviorClass) // Will be instantiated by DI
503
+
504
+ // Register adapters
505
+ .use(new HttpAdapter())
506
+ .use(new WebSocketAdapter())
507
+
508
+ .build();
509
+ ```
510
+
511
+ ## Application Lifecycle
512
+
513
+ ```typescript
514
+ const app = await builder.build();
515
+
516
+ // Start the application (calls adapter.initialize())
517
+ await app.run();
518
+
519
+ // Application is now ready to handle requests
520
+ const response = await app.send(request);
521
+
522
+ // Stop the application (calls adapter.dispose())
523
+ await app.stop();
524
+ ```
525
+
526
+ ## Advanced Examples
527
+
528
+ ### Complete Application with All Features
529
+
530
+ ```typescript
531
+ import {
532
+ ApplicationBuilder,
533
+ BaseRequest,
534
+ BaseResponse,
535
+ SimpleHandler,
536
+ StreamingHandler,
537
+ IPipelineBehavior,
538
+ PipelineContext,
539
+ PipelineDelegate,
540
+ HandlerResult
541
+ } from '@oldzy/conduit';
542
+
543
+ // Services
544
+ class DatabaseService {
545
+ async query(sql: string) { /* ... */ }
546
+ }
547
+
548
+ class CacheService {
549
+ async get(key: string) { /* ... */ }
550
+ async set(key: string, value: any) { /* ... */ }
551
+ }
552
+
553
+ // Request/Response
554
+ class GetProductRequest extends BaseRequest {
555
+ constructor(public productId: string) {
556
+ super('GET_PRODUCT');
557
+ }
558
+ }
559
+
560
+ class ProductResponse extends BaseResponse {
561
+ constructor(public id: string, public name: string, public price: number) {
562
+ super('PRODUCT_RESPONSE');
563
+ }
564
+ }
565
+
566
+ // Handler with dependencies
567
+ class GetProductHandler extends SimpleHandler<GetProductRequest, ProductResponse> {
568
+ constructor(
569
+ private db: DatabaseService,
570
+ private cache: CacheService
571
+ ) {
572
+ super();
573
+ }
574
+
575
+ protected async handleSimple(request: GetProductRequest): Promise<ProductResponse> {
576
+ // Check cache first
577
+ const cached = await this.cache.get(`product:${request.productId}`);
578
+ if (cached) return cached;
579
+
580
+ // Query database
581
+ const product = await this.db.query(`SELECT * FROM products WHERE id = ?`, [request.productId]);
582
+ const response = new ProductResponse(product.id, product.name, product.price);
583
+
584
+ // Cache result
585
+ await this.cache.set(`product:${request.productId}`, response);
586
+
587
+ return response;
588
+ }
589
+ }
590
+
591
+ // Caching behavior
592
+ class CachingBehavior implements IPipelineBehavior {
593
+ constructor(private cache: CacheService) {}
594
+
595
+ async handle(context: PipelineContext, next: PipelineDelegate): HandlerResult<BaseResponse> {
596
+ const cacheKey = `${context.request.type}:${JSON.stringify(context.request)}`;
597
+
598
+ const cached = await this.cache.get(cacheKey);
599
+ if (cached) return cached;
600
+
601
+ const response = await next();
602
+
603
+ if (response instanceof BaseResponse && response.success) {
604
+ await this.cache.set(cacheKey, response);
605
+ }
606
+
607
+ return response;
608
+ }
609
+ }
610
+
611
+ // Validation behavior
612
+ class ValidationBehavior implements IPipelineBehavior {
613
+ async handle(context: PipelineContext, next: PipelineDelegate): HandlerResult<BaseResponse> {
614
+ // Add your validation logic
615
+ if (!context.request.type) {
616
+ const response = new BaseResponse('VALIDATION_ERROR');
617
+ response.addError('Request type is required');
618
+ return response;
619
+ }
620
+
621
+ return await next();
622
+ }
623
+ }
624
+
625
+ // Build the application
626
+ const app = await new ApplicationBuilder()
627
+ // Register services
628
+ .registerSingleton('DatabaseService', DatabaseService)
629
+ .registerSingleton('CacheService', CacheService)
630
+
631
+ // Register handler with factory
632
+ .registerFactory('GET_PRODUCT', (provider) => {
633
+ const db = provider.getRequiredService<DatabaseService>('DatabaseService');
634
+ const cache = provider.getRequiredService<CacheService>('CacheService');
635
+ return new GetProductHandler(db, cache);
636
+ })
637
+
638
+ // Register behaviors (order matters!)
639
+ .registerFactory('ValidationBehavior', (provider) => new ValidationBehavior())
640
+ .registerFactory('CachingBehavior', (provider) => {
641
+ const cache = provider.getRequiredService<CacheService>('CacheService');
642
+ return new CachingBehavior(cache);
643
+ })
644
+
645
+ .build();
646
+
647
+ await app.run();
648
+
649
+ // Use the application
650
+ const request = new GetProductRequest('123');
651
+ const response = await app.send<ProductResponse>(request);
652
+
653
+ console.log(response.name, response.price);
654
+ ```
655
+
656
+ ## Testing
657
+
658
+ Conduit is designed to be testable. You can easily mock services and test handlers in isolation:
659
+
660
+ ```typescript
661
+ import { describe, it, expect } from 'vitest';
662
+
663
+ describe('GetUserHandler', () => {
664
+ it('should return user data', async () => {
665
+ const mockRepo = {
666
+ getUser: async (id: string) => ({ id, name: 'Test User' })
667
+ };
668
+
669
+ const handler = new GetUserHandler(mockRepo as any);
670
+ const request = new GetUserRequest('123');
671
+
672
+ const response = await handler.handle(request);
673
+
674
+ expect(response.userName).toBe('Test User');
675
+ expect(response.success).toBe(true);
676
+ });
677
+ });
678
+ ```
679
+
680
+ ## API Reference
681
+
682
+ ### Core Classes
683
+
684
+ - **ApplicationBuilder** - Fluent API for building applications
685
+ - **Application** - Main application class
686
+ - **Mediator** - Core mediator implementation
687
+ - **ServiceProvider** - DI container
688
+ - **ServiceCollection** - Service registration
689
+
690
+ ### Base Classes
691
+
692
+ - **BaseRequest** - Base class for all requests
693
+ - **BaseResponse** - Base class for all responses
694
+ - **SimpleHandler** - Base class for simple handlers
695
+ - **StreamingHandler** - Base class for streaming handlers
696
+
697
+ ### Interfaces
698
+
699
+ - **IRequestHandler** - Handler interface
700
+ - **IPipelineBehavior** - Behavior/middleware interface
701
+ - **IApplicationAdapter** - Transport adapter interface
702
+
703
+ ### Types
704
+
705
+ - **ServiceLifetime** - Enum: Singleton, Scoped, Transient
706
+ - **HandlerResult** - Union: `Promise<TResponse> | Promise<AsyncIterable<TResponse>>`
707
+
708
+ ## Best Practices
709
+
710
+ 1. **Use specific request/response types** - Don't use generic types, create specific classes for each use case
711
+ 2. **Keep handlers focused** - Each handler should do one thing well
712
+ 3. **Use behaviors for cross-cutting concerns** - Don't repeat logging, validation, etc. in every handler
713
+ 4. **Register services by interface** - Use string/symbol identifiers for better testability
714
+ 5. **Handle errors in behaviors** - Use an error handling behavior instead of try-catch in every handler
715
+ 6. **Use dependency injection** - Don't create dependencies inside handlers, inject them
716
+ 7. **Separate transport concerns** - Keep business logic in handlers, transport logic in adapters
717
+ 8. **Choose the right service lifetime**:
718
+ - **Singleton** for stateless services, repositories, configuration
719
+ - **Scoped** for database transactions, request caching, request context
720
+ - **Transient** for lightweight, stateful operations
721
+ 9. **Leverage scoped services** - Use them for per-request resources that need cleanup (transactions, connections, caches)
722
+
20
723
  ## License
21
724
 
22
725
  MIT
@@ -13,8 +13,7 @@ declare abstract class BaseResponse extends BaseCommunicationObject {
13
13
  success: boolean;
14
14
  errors?: string[];
15
15
  readonly timestamp: Date;
16
- readonly requestUuid: string;
17
- constructor(type: string, requestUuid: string);
16
+ constructor(type: string);
18
17
  setErrors(errors: string[]): this;
19
18
  addError(error: string): this;
20
19
  }
@@ -13,8 +13,7 @@ declare abstract class BaseResponse extends BaseCommunicationObject {
13
13
  success: boolean;
14
14
  errors?: string[];
15
15
  readonly timestamp: Date;
16
- readonly requestUuid: string;
17
- constructor(type: string, requestUuid: string);
16
+ constructor(type: string);
18
17
  setErrors(errors: string[]): this;
19
18
  addError(error: string): this;
20
19
  }
@@ -0,0 +1,15 @@
1
+ import { S as ServiceProvider } from './ServiceProvider-BcW9XXlN.js';
2
+ import { b as BaseResponse, a as BaseRequest } from './IRequestHandler-D8MPY7jr.js';
3
+
4
+ declare class Mediator {
5
+ private serviceProvider;
6
+ private behaviors;
7
+ constructor(serviceProvider: ServiceProvider);
8
+ send<TResponse extends BaseResponse>(request: BaseRequest): Promise<TResponse>;
9
+ stream<TResponse extends BaseResponse>(request: BaseRequest): Promise<AsyncIterable<TResponse>>;
10
+ private executeHandler;
11
+ private executePipeline;
12
+ private isAsyncIterable;
13
+ }
14
+
15
+ export { Mediator as M };
@@ -0,0 +1,15 @@
1
+ import { S as ServiceProvider } from './ServiceProvider-BcW9XXlN.mjs';
2
+ import { b as BaseResponse, a as BaseRequest } from './IRequestHandler-D8MPY7jr.mjs';
3
+
4
+ declare class Mediator {
5
+ private serviceProvider;
6
+ private behaviors;
7
+ constructor(serviceProvider: ServiceProvider);
8
+ send<TResponse extends BaseResponse>(request: BaseRequest): Promise<TResponse>;
9
+ stream<TResponse extends BaseResponse>(request: BaseRequest): Promise<AsyncIterable<TResponse>>;
10
+ private executeHandler;
11
+ private executePipeline;
12
+ private isAsyncIterable;
13
+ }
14
+
15
+ export { Mediator as M };
@@ -1,13 +1,13 @@
1
1
  import { S as ServiceCollection } from '../ServiceCollection-3wUO7p8g.mjs';
2
2
  import { S as ServiceProvider, b as ServiceLifetime } from '../ServiceProvider-BcW9XXlN.mjs';
3
- import { b as BaseResponse, a as BaseRequest, H as HandlerResult, I as IRequestHandler } from '../IRequestHandler-CjLrozYA.mjs';
3
+ import { b as BaseResponse, a as BaseRequest, I as IRequestHandler } from '../IRequestHandler-D8MPY7jr.mjs';
4
4
  import { IPipelineBehavior } from '../pipeline/index.mjs';
5
- import { M as Mediator } from '../Mediator-CF-4m1QF.mjs';
5
+ import { M as Mediator } from '../Mediator-DHJ4zHMn.mjs';
6
6
 
7
7
  interface IApplicationAdapter {
8
8
  readonly name: string;
9
9
  configure(services: ServiceCollection): void | Promise<void>;
10
- initialize?(): void | Promise<void>;
10
+ initialize?(app: Application): void | Promise<void>;
11
11
  dispose?(): void | Promise<void>;
12
12
  }
13
13
 
@@ -19,7 +19,8 @@ declare class Application {
19
19
  constructor(serviceProvider: ServiceProvider, mediator: Mediator, adapters: IApplicationAdapter[]);
20
20
  run(): Promise<void>;
21
21
  stop(): Promise<void>;
22
- send<TResponse extends BaseResponse>(request: BaseRequest): HandlerResult<TResponse>;
22
+ send<TResponse extends BaseResponse>(request: BaseRequest): Promise<TResponse>;
23
+ stream<TResponse extends BaseResponse>(request: BaseRequest): Promise<AsyncIterable<TResponse>>;
23
24
  getServiceProvider(): ServiceProvider;
24
25
  getMediator(): Mediator;
25
26
  get running(): boolean;
@@ -32,7 +33,7 @@ declare class ApplicationBuilder {
32
33
  constructor();
33
34
  registerHandler<TRequest extends BaseRequest, TResponse extends BaseResponse>(requestType: string | symbol, handler: (new (...args: any[]) => IRequestHandler<TRequest, TResponse>) | IRequestHandler<TRequest, TResponse>, lifetime?: ServiceLifetime): this;
34
35
  registerHandlers(handlers: Map<string | symbol, new (...args: any[]) => IRequestHandler<any, any>>): this;
35
- registerBehavior<TRequest extends BaseRequest, TResponse extends BaseResponse>(behavior: (new (...args: any[]) => IPipelineBehavior<TRequest, TResponse>) | IPipelineBehavior<TRequest, TResponse>): this;
36
+ registerBehavior(behavior: (new (...args: any[]) => IPipelineBehavior) | IPipelineBehavior): this;
36
37
  registerSingleton<T>(serviceIdentifier: string | symbol, implementation: (new (...args: any[]) => T) | T): this;
37
38
  registerScoped<T>(serviceIdentifier: string | symbol, implementation: new (...args: any[]) => T): this;
38
39
  registerTransient<T>(serviceIdentifier: string | symbol, implementation: new (...args: any[]) => T): this;
@@ -1,13 +1,13 @@
1
1
  import { S as ServiceCollection } from '../ServiceCollection-B8PXr0Uo.js';
2
2
  import { S as ServiceProvider, b as ServiceLifetime } from '../ServiceProvider-BcW9XXlN.js';
3
- import { b as BaseResponse, a as BaseRequest, H as HandlerResult, I as IRequestHandler } from '../IRequestHandler-CjLrozYA.js';
3
+ import { b as BaseResponse, a as BaseRequest, I as IRequestHandler } from '../IRequestHandler-D8MPY7jr.js';
4
4
  import { IPipelineBehavior } from '../pipeline/index.js';
5
- import { M as Mediator } from '../Mediator-DkYg4E8y.js';
5
+ import { M as Mediator } from '../Mediator-D3eBV427.js';
6
6
 
7
7
  interface IApplicationAdapter {
8
8
  readonly name: string;
9
9
  configure(services: ServiceCollection): void | Promise<void>;
10
- initialize?(): void | Promise<void>;
10
+ initialize?(app: Application): void | Promise<void>;
11
11
  dispose?(): void | Promise<void>;
12
12
  }
13
13
 
@@ -19,7 +19,8 @@ declare class Application {
19
19
  constructor(serviceProvider: ServiceProvider, mediator: Mediator, adapters: IApplicationAdapter[]);
20
20
  run(): Promise<void>;
21
21
  stop(): Promise<void>;
22
- send<TResponse extends BaseResponse>(request: BaseRequest): HandlerResult<TResponse>;
22
+ send<TResponse extends BaseResponse>(request: BaseRequest): Promise<TResponse>;
23
+ stream<TResponse extends BaseResponse>(request: BaseRequest): Promise<AsyncIterable<TResponse>>;
23
24
  getServiceProvider(): ServiceProvider;
24
25
  getMediator(): Mediator;
25
26
  get running(): boolean;
@@ -32,7 +33,7 @@ declare class ApplicationBuilder {
32
33
  constructor();
33
34
  registerHandler<TRequest extends BaseRequest, TResponse extends BaseResponse>(requestType: string | symbol, handler: (new (...args: any[]) => IRequestHandler<TRequest, TResponse>) | IRequestHandler<TRequest, TResponse>, lifetime?: ServiceLifetime): this;
34
35
  registerHandlers(handlers: Map<string | symbol, new (...args: any[]) => IRequestHandler<any, any>>): this;
35
- registerBehavior<TRequest extends BaseRequest, TResponse extends BaseResponse>(behavior: (new (...args: any[]) => IPipelineBehavior<TRequest, TResponse>) | IPipelineBehavior<TRequest, TResponse>): this;
36
+ registerBehavior(behavior: (new (...args: any[]) => IPipelineBehavior) | IPipelineBehavior): this;
36
37
  registerSingleton<T>(serviceIdentifier: string | symbol, implementation: (new (...args: any[]) => T) | T): this;
37
38
  registerScoped<T>(serviceIdentifier: string | symbol, implementation: new (...args: any[]) => T): this;
38
39
  registerTransient<T>(serviceIdentifier: string | symbol, implementation: new (...args: any[]) => T): this;
@@ -1,2 +1,2 @@
1
1
  'use strict';require('reflect-metadata');/* conduit - MIT License */
2
- var P=Object.defineProperty;var E=(o,e,t)=>e in o?P(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var n=(o,e)=>P(o,"name",{value:e,configurable:true});var i=(o,e,t)=>E(o,typeof e!="symbol"?e+"":e,t);var s=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var l=class l{constructor(e,t){i(this,"serviceDescriptors");i(this,"singletons",new Map);i(this,"scopedInstances",new Map);i(this,"parent");i(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case s.Singleton:return this.resolveSingleton(e);case s.Scoped:return this.resolveScoped(e);case s.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let c=r.map(d=>this.getRequiredService(d));return new t(...c)}let p=(Reflect.getMetadata("design:paramtypes",t)||[]).map((c,d)=>{let T=Reflect.getMetadata("inject:params",t)?.[d];if(T)return this.getRequiredService(T);let R=c.name||c;return this.getRequiredService(R)});return new t(...p)}createScope(){let e=new l(this.serviceDescriptors,this);return {serviceProvider:e,dispose:n(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};n(l,"ServiceProvider");var u=l;var m=class m{constructor(){i(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:s.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Transient}),this}addFactory(e,t,r=s.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};n(m,"ServiceCollection");var v=m;var S=class S{constructor(e){i(this,"request");i(this,"response");i(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};n(S,"PipelineContext");var f=S;var w=class w{constructor(e){i(this,"serviceProvider");i(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let r=new f(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(r,t,this.behaviors)}async executePipeline(e,t,r){let a=0,p=n(async()=>{if(a<r.length)return await r[a++].handle(e,p);let c=await t.handle(e.request);return e.response=c,c},"next");return await p()}};n(w,"Mediator");var g=w;var y=class y{constructor(e,t,r){i(this,"serviceProvider");i(this,"mediator");i(this,"isRunning",false);i(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize();this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};n(y,"Application");var h=y;var k="PipelineBehaviors",I=class I{constructor(){i(this,"services");i(this,"adapters",[]);i(this,"pipelineBehaviors",[]);this.services=new v;}registerHandler(e,t,r=s.Transient){if(typeof t=="function")switch(r){case s.Singleton:this.services.addSingleton(e,t);break;case s.Scoped:this.services.addScoped(e,t);break;case s.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=s.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(k,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new g(e);return new h(e,t,this.adapters)}};n(I,"ApplicationBuilder");var D=I;exports.Application=h;exports.ApplicationBuilder=D;
2
+ var E=Object.defineProperty;var T=(o,e,t)=>e in o?E(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var n=(o,e)=>E(o,"name",{value:e,configurable:true});var s=(o,e,t)=>T(o,typeof e!="symbol"?e+"":e,t);var i=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var l=class l{constructor(e,t){s(this,"serviceDescriptors");s(this,"singletons",new Map);s(this,"scopedInstances",new Map);s(this,"parent");s(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case i.Singleton:return this.resolveSingleton(e);case i.Scoped:return this.resolveScoped(e);case i.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let c=r.map(d=>this.getRequiredService(d));return new t(...c)}let p=(Reflect.getMetadata("design:paramtypes",t)||[]).map((c,d)=>{let P=Reflect.getMetadata("inject:params",t)?.[d];if(P)return this.getRequiredService(P);let R=c.name||c;return this.getRequiredService(R)});return new t(...p)}createScope(){let e=new l(this.serviceDescriptors,this);return {serviceProvider:e,dispose:n(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};n(l,"ServiceProvider");var u=l;var g=class g{constructor(){s(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:i.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Transient}),this}addFactory(e,t,r=i.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};n(g,"ServiceCollection");var v=g;var S=class S{constructor(e){s(this,"request");s(this,"response");s(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};n(S,"PipelineContext");var f=S;var w=class w{constructor(e){s(this,"serviceProvider");s(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(this.isAsyncIterable(r))throw new Error("Handler returned a stream. Use stream() method instead of send().");return r}finally{t.dispose();}}async stream(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(!this.isAsyncIterable(r))throw new Error("Handler did not return a stream. Use send() method instead of stream().");return r}finally{t.dispose();}}async executeHandler(e,t){let r=t.getService(e.type);if(!r)throw new Error(`No handler registered for request type: ${String(e.type)}`);let a=new f(e);return this.behaviors.length===0?await r.handle(e):await this.executePipeline(a,r,this.behaviors)}async executePipeline(e,t,r){let a=0,p=n(async()=>{if(a<r.length)return await r[a++].handle(e,p);let c=await t.handle(e.request);return e.response=c,c},"next");return await p()}isAsyncIterable(e){return e!=null&&typeof e[Symbol.asyncIterator]=="function"}};n(w,"Mediator");var m=w;var y=class y{constructor(e,t,r){s(this,"serviceProvider");s(this,"mediator");s(this,"isRunning",false);s(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize(this);this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}async stream(e){if(!this.isRunning)throw new Error("Application must be running before streaming requests. Call app.run() first.");return this.mediator.stream(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};n(y,"Application");var h=y;var b="PipelineBehaviors",D=class D{constructor(){s(this,"services");s(this,"adapters",[]);s(this,"pipelineBehaviors",[]);this.services=new v;}registerHandler(e,t,r=i.Transient){if(typeof t=="function")switch(r){case i.Singleton:this.services.addSingleton(e,t);break;case i.Scoped:this.services.addScoped(e,t);break;case i.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=i.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(b,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new m(e);return new h(e,t,this.adapters)}};n(D,"ApplicationBuilder");var I=D;exports.Application=h;exports.ApplicationBuilder=I;
@@ -1,2 +1,2 @@
1
1
  import'reflect-metadata';/* conduit - MIT License */
2
- var P=Object.defineProperty;var E=(o,e,t)=>e in o?P(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var n=(o,e)=>P(o,"name",{value:e,configurable:true});var i=(o,e,t)=>E(o,typeof e!="symbol"?e+"":e,t);var s=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var l=class l{constructor(e,t){i(this,"serviceDescriptors");i(this,"singletons",new Map);i(this,"scopedInstances",new Map);i(this,"parent");i(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case s.Singleton:return this.resolveSingleton(e);case s.Scoped:return this.resolveScoped(e);case s.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let c=r.map(d=>this.getRequiredService(d));return new t(...c)}let p=(Reflect.getMetadata("design:paramtypes",t)||[]).map((c,d)=>{let T=Reflect.getMetadata("inject:params",t)?.[d];if(T)return this.getRequiredService(T);let R=c.name||c;return this.getRequiredService(R)});return new t(...p)}createScope(){let e=new l(this.serviceDescriptors,this);return {serviceProvider:e,dispose:n(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};n(l,"ServiceProvider");var u=l;var m=class m{constructor(){i(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:s.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Transient}),this}addFactory(e,t,r=s.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:s.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};n(m,"ServiceCollection");var v=m;var S=class S{constructor(e){i(this,"request");i(this,"response");i(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};n(S,"PipelineContext");var f=S;var w=class w{constructor(e){i(this,"serviceProvider");i(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let r=new f(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(r,t,this.behaviors)}async executePipeline(e,t,r){let a=0,p=n(async()=>{if(a<r.length)return await r[a++].handle(e,p);let c=await t.handle(e.request);return e.response=c,c},"next");return await p()}};n(w,"Mediator");var g=w;var y=class y{constructor(e,t,r){i(this,"serviceProvider");i(this,"mediator");i(this,"isRunning",false);i(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize();this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};n(y,"Application");var h=y;var k="PipelineBehaviors",I=class I{constructor(){i(this,"services");i(this,"adapters",[]);i(this,"pipelineBehaviors",[]);this.services=new v;}registerHandler(e,t,r=s.Transient){if(typeof t=="function")switch(r){case s.Singleton:this.services.addSingleton(e,t);break;case s.Scoped:this.services.addScoped(e,t);break;case s.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=s.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(k,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new g(e);return new h(e,t,this.adapters)}};n(I,"ApplicationBuilder");var D=I;export{h as Application,D as ApplicationBuilder};
2
+ var E=Object.defineProperty;var T=(o,e,t)=>e in o?E(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var n=(o,e)=>E(o,"name",{value:e,configurable:true});var s=(o,e,t)=>T(o,typeof e!="symbol"?e+"":e,t);var i=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var l=class l{constructor(e,t){s(this,"serviceDescriptors");s(this,"singletons",new Map);s(this,"scopedInstances",new Map);s(this,"parent");s(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case i.Singleton:return this.resolveSingleton(e);case i.Scoped:return this.resolveScoped(e);case i.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let c=r.map(d=>this.getRequiredService(d));return new t(...c)}let p=(Reflect.getMetadata("design:paramtypes",t)||[]).map((c,d)=>{let P=Reflect.getMetadata("inject:params",t)?.[d];if(P)return this.getRequiredService(P);let R=c.name||c;return this.getRequiredService(R)});return new t(...p)}createScope(){let e=new l(this.serviceDescriptors,this);return {serviceProvider:e,dispose:n(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};n(l,"ServiceProvider");var u=l;var g=class g{constructor(){s(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:i.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Transient}),this}addFactory(e,t,r=i.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:i.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};n(g,"ServiceCollection");var v=g;var S=class S{constructor(e){s(this,"request");s(this,"response");s(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};n(S,"PipelineContext");var f=S;var w=class w{constructor(e){s(this,"serviceProvider");s(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(this.isAsyncIterable(r))throw new Error("Handler returned a stream. Use stream() method instead of send().");return r}finally{t.dispose();}}async stream(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(!this.isAsyncIterable(r))throw new Error("Handler did not return a stream. Use send() method instead of stream().");return r}finally{t.dispose();}}async executeHandler(e,t){let r=t.getService(e.type);if(!r)throw new Error(`No handler registered for request type: ${String(e.type)}`);let a=new f(e);return this.behaviors.length===0?await r.handle(e):await this.executePipeline(a,r,this.behaviors)}async executePipeline(e,t,r){let a=0,p=n(async()=>{if(a<r.length)return await r[a++].handle(e,p);let c=await t.handle(e.request);return e.response=c,c},"next");return await p()}isAsyncIterable(e){return e!=null&&typeof e[Symbol.asyncIterator]=="function"}};n(w,"Mediator");var m=w;var y=class y{constructor(e,t,r){s(this,"serviceProvider");s(this,"mediator");s(this,"isRunning",false);s(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize(this);this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}async stream(e){if(!this.isRunning)throw new Error("Application must be running before streaming requests. Call app.run() first.");return this.mediator.stream(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};n(y,"Application");var h=y;var b="PipelineBehaviors",D=class D{constructor(){s(this,"services");s(this,"adapters",[]);s(this,"pipelineBehaviors",[]);this.services=new v;}registerHandler(e,t,r=i.Transient){if(typeof t=="function")switch(r){case i.Singleton:this.services.addSingleton(e,t);break;case i.Scoped:this.services.addScoped(e,t);break;case i.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=i.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(b,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new m(e);return new h(e,t,this.adapters)}};n(D,"ApplicationBuilder");var I=D;export{h as Application,I as ApplicationBuilder};
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  export { S as ServiceCollection } from './ServiceCollection-3wUO7p8g.mjs';
2
2
  export { I as IServiceScope, a as ServiceDescriptor, b as ServiceLifetime, S as ServiceProvider } from './ServiceProvider-BcW9XXlN.mjs';
3
3
  export { Inject } from './di/index.mjs';
4
- export { B as BaseCommunicationObject, a as BaseRequest, b as BaseResponse, H as HandlerResult, I as IRequestHandler } from './IRequestHandler-CjLrozYA.mjs';
5
- export { M as Mediator } from './Mediator-CF-4m1QF.mjs';
4
+ export { B as BaseCommunicationObject, a as BaseRequest, b as BaseResponse, H as HandlerResult, I as IRequestHandler } from './IRequestHandler-D8MPY7jr.mjs';
5
+ export { M as Mediator } from './Mediator-DHJ4zHMn.mjs';
6
6
  export { SimpleHandler, StreamingHandler } from './mediator/index.mjs';
7
7
  export { IPipelineBehavior, PipelineContext, PipelineDelegate } from './pipeline/index.mjs';
8
8
  export { Application, ApplicationBuilder, IApplicationAdapter } from './application/index.mjs';
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export { S as ServiceCollection } from './ServiceCollection-B8PXr0Uo.js';
2
2
  export { I as IServiceScope, a as ServiceDescriptor, b as ServiceLifetime, S as ServiceProvider } from './ServiceProvider-BcW9XXlN.js';
3
3
  export { Inject } from './di/index.js';
4
- export { B as BaseCommunicationObject, a as BaseRequest, b as BaseResponse, H as HandlerResult, I as IRequestHandler } from './IRequestHandler-CjLrozYA.js';
5
- export { M as Mediator } from './Mediator-DkYg4E8y.js';
4
+ export { B as BaseCommunicationObject, a as BaseRequest, b as BaseResponse, H as HandlerResult, I as IRequestHandler } from './IRequestHandler-D8MPY7jr.js';
5
+ export { M as Mediator } from './Mediator-D3eBV427.js';
6
6
  export { SimpleHandler, StreamingHandler } from './mediator/index.js';
7
7
  export { IPipelineBehavior, PipelineContext, PipelineDelegate } from './pipeline/index.js';
8
8
  export { Application, ApplicationBuilder, IApplicationAdapter } from './application/index.js';
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  'use strict';require('reflect-metadata');var uuid=require('uuid');/* conduit - MIT License */
2
- var F=Object.defineProperty;var $=(o,e,t)=>e in o?F(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var i=(o,e)=>F(o,"name",{value:e,configurable:true});var s=(o,e,t)=>$(o,typeof e!="symbol"?e+"":e,t);var n=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var g=class g{constructor(e,t){s(this,"serviceDescriptors");s(this,"singletons",new Map);s(this,"scopedInstances",new Map);s(this,"parent");s(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case n.Singleton:return this.resolveSingleton(e);case n.Scoped:return this.resolveScoped(e);case n.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let h=r.map(v=>this.getRequiredService(v));return new t(...h)}let c=(Reflect.getMetadata("design:paramtypes",t)||[]).map((h,v)=>{let q=Reflect.getMetadata("inject:params",t)?.[v];if(q)return this.getRequiredService(q);let N=h.name||h;return this.getRequiredService(N)});return new t(...c)}createScope(){let e=new g(this.serviceDescriptors,this);return {serviceProvider:e,dispose:i(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};i(g,"ServiceProvider");var u=g;var S=class S{constructor(){s(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:n.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Transient}),this}addFactory(e,t,r=n.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};i(S,"ServiceCollection");var d=S;function B(o){return (e,t,r)=>{let c={...Reflect.getOwnMetadata("inject:params",e)||{}};c[r]=o,Reflect.defineMetadata("inject:params",c,e);}}i(B,"Inject");var w=class w{constructor(e){s(this,"request");s(this,"response");s(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};i(w,"PipelineContext");var l=w;var x=class x{constructor(e){s(this,"serviceProvider");s(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let r=new l(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(r,t,this.behaviors)}async executePipeline(e,t,r){let a=0,c=i(async()=>{if(a<r.length)return await r[a++].handle(e,c);let h=await t.handle(e.request);return e.response=h,h},"next");return await c()}};i(x,"Mediator");var m=x;var D=class D{handle(e){return this.handleSimple(e)}};i(D,"SimpleHandler");var y=D,P=class P{handle(e){return this.handleStream(e)}};i(P,"StreamingHandler");var I=P;var E=class E{constructor(e){s(this,"type");this.type=e;}};i(E,"BaseCommunicationObject");var p=E;var R=class R extends p{constructor(t){super(t);s(this,"uuid");s(this,"timestamp");this.uuid=uuid.v4(),this.timestamp=new Date;}};i(R,"BaseRequest");var T=R;var k=class k extends p{constructor(t,r){super(t);s(this,"success");s(this,"errors");s(this,"timestamp");s(this,"requestUuid");this.timestamp=new Date,this.success=true,this.requestUuid=r;}setErrors(t){return this.success=false,this.errors=t,this}addError(t){return this.errors||(this.errors=[]),this.errors.push(t),this.success=false,this}};i(k,"BaseResponse");var b=k;var j=class j{constructor(e,t,r){s(this,"serviceProvider");s(this,"mediator");s(this,"isRunning",false);s(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize();this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};i(j,"Application");var f=j;var L="PipelineBehaviors",C=class C{constructor(){s(this,"services");s(this,"adapters",[]);s(this,"pipelineBehaviors",[]);this.services=new d;}registerHandler(e,t,r=n.Transient){if(typeof t=="function")switch(r){case n.Singleton:this.services.addSingleton(e,t);break;case n.Scoped:this.services.addScoped(e,t);break;case n.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=n.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(L,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new m(e);return new f(e,t,this.adapters)}};i(C,"ApplicationBuilder");var M=C;exports.Application=f;exports.ApplicationBuilder=M;exports.BaseCommunicationObject=p;exports.BaseRequest=T;exports.BaseResponse=b;exports.Inject=B;exports.Mediator=m;exports.PipelineContext=l;exports.ServiceCollection=d;exports.ServiceLifetime=n;exports.ServiceProvider=u;exports.SimpleHandler=y;exports.StreamingHandler=I;
2
+ var H=Object.defineProperty;var F=(o,e,t)=>e in o?H(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var i=(o,e)=>H(o,"name",{value:e,configurable:true});var s=(o,e,t)=>F(o,typeof e!="symbol"?e+"":e,t);var n=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var g=class g{constructor(e,t){s(this,"serviceDescriptors");s(this,"singletons",new Map);s(this,"scopedInstances",new Map);s(this,"parent");s(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case n.Singleton:return this.resolveSingleton(e);case n.Scoped:return this.resolveScoped(e);case n.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let h=r.map(v=>this.getRequiredService(v));return new t(...h)}let c=(Reflect.getMetadata("design:paramtypes",t)||[]).map((h,v)=>{let A=Reflect.getMetadata("inject:params",t)?.[v];if(A)return this.getRequiredService(A);let q=h.name||h;return this.getRequiredService(q)});return new t(...c)}createScope(){let e=new g(this.serviceDescriptors,this);return {serviceProvider:e,dispose:i(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};i(g,"ServiceProvider");var u=g;var S=class S{constructor(){s(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:n.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Transient}),this}addFactory(e,t,r=n.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};i(S,"ServiceCollection");var d=S;function N(o){return (e,t,r)=>{let c={...Reflect.getOwnMetadata("inject:params",e)||{}};c[r]=o,Reflect.defineMetadata("inject:params",c,e);}}i(N,"Inject");var w=class w{constructor(e){s(this,"request");s(this,"response");s(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};i(w,"PipelineContext");var l=w;var y=class y{constructor(e){s(this,"serviceProvider");s(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(this.isAsyncIterable(r))throw new Error("Handler returned a stream. Use stream() method instead of send().");return r}finally{t.dispose();}}async stream(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(!this.isAsyncIterable(r))throw new Error("Handler did not return a stream. Use send() method instead of stream().");return r}finally{t.dispose();}}async executeHandler(e,t){let r=t.getService(e.type);if(!r)throw new Error(`No handler registered for request type: ${String(e.type)}`);let a=new l(e);return this.behaviors.length===0?await r.handle(e):await this.executePipeline(a,r,this.behaviors)}async executePipeline(e,t,r){let a=0,c=i(async()=>{if(a<r.length)return await r[a++].handle(e,c);let h=await t.handle(e.request);return e.response=h,h},"next");return await c()}isAsyncIterable(e){return e!=null&&typeof e[Symbol.asyncIterator]=="function"}};i(y,"Mediator");var m=y;var D=class D{handle(e){return this.handleSimple(e)}};i(D,"SimpleHandler");var x=D,P=class P{handle(e){return this.handleStream(e)}};i(P,"StreamingHandler");var I=P;var E=class E{constructor(e){s(this,"type");this.type=e;}};i(E,"BaseCommunicationObject");var p=E;var R=class R extends p{constructor(t){super(t);s(this,"uuid");s(this,"timestamp");this.uuid=uuid.v4(),this.timestamp=new Date;}};i(R,"BaseRequest");var b=R;var k=class k extends p{constructor(t){super(t);s(this,"success");s(this,"errors");s(this,"timestamp");this.timestamp=new Date,this.success=true;}setErrors(t){return this.success=false,this.errors=t,this}addError(t){return this.errors||(this.errors=[]),this.errors.push(t),this.success=false,this}};i(k,"BaseResponse");var T=k;var M=class M{constructor(e,t,r){s(this,"serviceProvider");s(this,"mediator");s(this,"isRunning",false);s(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize(this);this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}async stream(e){if(!this.isRunning)throw new Error("Application must be running before streaming requests. Call app.run() first.");return this.mediator.stream(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};i(M,"Application");var f=M;var B="PipelineBehaviors",C=class C{constructor(){s(this,"services");s(this,"adapters",[]);s(this,"pipelineBehaviors",[]);this.services=new d;}registerHandler(e,t,r=n.Transient){if(typeof t=="function")switch(r){case n.Singleton:this.services.addSingleton(e,t);break;case n.Scoped:this.services.addScoped(e,t);break;case n.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=n.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(B,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new m(e);return new f(e,t,this.adapters)}};i(C,"ApplicationBuilder");var j=C;exports.Application=f;exports.ApplicationBuilder=j;exports.BaseCommunicationObject=p;exports.BaseRequest=b;exports.BaseResponse=T;exports.Inject=N;exports.Mediator=m;exports.PipelineContext=l;exports.ServiceCollection=d;exports.ServiceLifetime=n;exports.ServiceProvider=u;exports.SimpleHandler=x;exports.StreamingHandler=I;
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  import'reflect-metadata';import {v4}from'uuid';/* conduit - MIT License */
2
- var F=Object.defineProperty;var $=(o,e,t)=>e in o?F(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var i=(o,e)=>F(o,"name",{value:e,configurable:true});var s=(o,e,t)=>$(o,typeof e!="symbol"?e+"":e,t);var n=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var g=class g{constructor(e,t){s(this,"serviceDescriptors");s(this,"singletons",new Map);s(this,"scopedInstances",new Map);s(this,"parent");s(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case n.Singleton:return this.resolveSingleton(e);case n.Scoped:return this.resolveScoped(e);case n.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let h=r.map(v=>this.getRequiredService(v));return new t(...h)}let c=(Reflect.getMetadata("design:paramtypes",t)||[]).map((h,v)=>{let q=Reflect.getMetadata("inject:params",t)?.[v];if(q)return this.getRequiredService(q);let N=h.name||h;return this.getRequiredService(N)});return new t(...c)}createScope(){let e=new g(this.serviceDescriptors,this);return {serviceProvider:e,dispose:i(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};i(g,"ServiceProvider");var u=g;var S=class S{constructor(){s(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:n.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Transient}),this}addFactory(e,t,r=n.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};i(S,"ServiceCollection");var d=S;function B(o){return (e,t,r)=>{let c={...Reflect.getOwnMetadata("inject:params",e)||{}};c[r]=o,Reflect.defineMetadata("inject:params",c,e);}}i(B,"Inject");var w=class w{constructor(e){s(this,"request");s(this,"response");s(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};i(w,"PipelineContext");var l=w;var x=class x{constructor(e){s(this,"serviceProvider");s(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let r=new l(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(r,t,this.behaviors)}async executePipeline(e,t,r){let a=0,c=i(async()=>{if(a<r.length)return await r[a++].handle(e,c);let h=await t.handle(e.request);return e.response=h,h},"next");return await c()}};i(x,"Mediator");var m=x;var D=class D{handle(e){return this.handleSimple(e)}};i(D,"SimpleHandler");var y=D,P=class P{handle(e){return this.handleStream(e)}};i(P,"StreamingHandler");var I=P;var E=class E{constructor(e){s(this,"type");this.type=e;}};i(E,"BaseCommunicationObject");var p=E;var R=class R extends p{constructor(t){super(t);s(this,"uuid");s(this,"timestamp");this.uuid=v4(),this.timestamp=new Date;}};i(R,"BaseRequest");var T=R;var k=class k extends p{constructor(t,r){super(t);s(this,"success");s(this,"errors");s(this,"timestamp");s(this,"requestUuid");this.timestamp=new Date,this.success=true,this.requestUuid=r;}setErrors(t){return this.success=false,this.errors=t,this}addError(t){return this.errors||(this.errors=[]),this.errors.push(t),this.success=false,this}};i(k,"BaseResponse");var b=k;var j=class j{constructor(e,t,r){s(this,"serviceProvider");s(this,"mediator");s(this,"isRunning",false);s(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize();this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};i(j,"Application");var f=j;var L="PipelineBehaviors",C=class C{constructor(){s(this,"services");s(this,"adapters",[]);s(this,"pipelineBehaviors",[]);this.services=new d;}registerHandler(e,t,r=n.Transient){if(typeof t=="function")switch(r){case n.Singleton:this.services.addSingleton(e,t);break;case n.Scoped:this.services.addScoped(e,t);break;case n.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=n.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(L,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new m(e);return new f(e,t,this.adapters)}};i(C,"ApplicationBuilder");var M=C;export{f as Application,M as ApplicationBuilder,p as BaseCommunicationObject,T as BaseRequest,b as BaseResponse,B as Inject,m as Mediator,l as PipelineContext,d as ServiceCollection,n as ServiceLifetime,u as ServiceProvider,y as SimpleHandler,I as StreamingHandler};
2
+ var H=Object.defineProperty;var F=(o,e,t)=>e in o?H(o,e,{enumerable:true,configurable:true,writable:true,value:t}):o[e]=t;var i=(o,e)=>H(o,"name",{value:e,configurable:true});var s=(o,e,t)=>F(o,typeof e!="symbol"?e+"":e,t);var n=(function(o){return o.Singleton="SINGLETON",o.Scoped="SCOPED",o.Transient="TRANSIENT",o})({});var g=class g{constructor(e,t){s(this,"serviceDescriptors");s(this,"singletons",new Map);s(this,"scopedInstances",new Map);s(this,"parent");s(this,"resolutionStack",[]);this.serviceDescriptors=e,this.parent=t;}getService(e){try{return this.getRequiredService(e)}catch{return}}getRequiredService(e){let t=this.resolutionStack.length===0;if(this.resolutionStack.includes(e)){let r=[...this.resolutionStack,e].map(a=>String(a)).join(" \u2192 ");throw new Error(`Circular dependency detected: ${r}`)}this.resolutionStack.push(e);try{let r=this.serviceDescriptors.find(a=>a.serviceIdentifier===e);if(!r){if(this.parent)return this.parent.getRequiredService(e);throw new Error(`Service '${String(e)}' not registered`)}return this.resolveService(r)}catch(r){throw this.resolutionStack.pop(),r}finally{this.resolutionStack[this.resolutionStack.length-1]===e&&this.resolutionStack.pop(),t&&(this.resolutionStack=[]);}}resolveService(e){switch(e.lifetime){case n.Singleton:return this.resolveSingleton(e);case n.Scoped:return this.resolveScoped(e);case n.Transient:return this.resolveTransient(e);default:throw new Error(`Unknown lifetime: ${e.lifetime}`)}}resolveSingleton(e){let{serviceIdentifier:t}=e;if(this.singletons.has(t))return this.singletons.get(t);let r=this.createInstance(e);return this.singletons.set(t,r),r}resolveScoped(e){let{serviceIdentifier:t}=e;if(!this.parent)throw new Error(`Cannot resolve scoped service '${String(t)}' from root provider. Use createScope() first.`);if(this.scopedInstances.has(t))return this.scopedInstances.get(t);let r=this.createInstance(e);return this.scopedInstances.set(t,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.constructInstance(e);throw new Error(`Cannot create instance for service '${String(e.serviceIdentifier)}'`)}constructInstance(e){let{implementationType:t,dependencies:r}=e;if(!t)throw new Error("Implementation type is required");if(r&&r.length>0){let h=r.map(v=>this.getRequiredService(v));return new t(...h)}let c=(Reflect.getMetadata("design:paramtypes",t)||[]).map((h,v)=>{let A=Reflect.getMetadata("inject:params",t)?.[v];if(A)return this.getRequiredService(A);let q=h.name||h;return this.getRequiredService(q)});return new t(...c)}createScope(){let e=new g(this.serviceDescriptors,this);return {serviceProvider:e,dispose:i(()=>{e.scopedInstances.clear();},"dispose")}}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)||(this.parent?.has(e)??false)}};i(g,"ServiceProvider");var u=g;var S=class S{constructor(){s(this,"serviceDescriptors",[]);}addSingleton(e,t){return typeof t=="function"?this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Singleton}):this.serviceDescriptors.push({serviceIdentifier:e,implementationInstance:t,lifetime:n.Singleton}),this}addScoped(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped}),this}addTransient(e,t){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Transient}),this}addFactory(e,t,r=n.Transient){return this.serviceDescriptors.push({serviceIdentifier:e,implementationFactory:t,lifetime:r}),this}addScopedWithDependencies(e,t,r){return this.serviceDescriptors.push({serviceIdentifier:e,implementationType:t,lifetime:n.Scoped,dependencies:r}),this}buildServiceProvider(){return new u([...this.serviceDescriptors])}getDescriptors(){return [...this.serviceDescriptors]}has(e){return this.serviceDescriptors.some(t=>t.serviceIdentifier===e)}get count(){return this.serviceDescriptors.length}};i(S,"ServiceCollection");var d=S;function N(o){return (e,t,r)=>{let c={...Reflect.getOwnMetadata("inject:params",e)||{}};c[r]=o,Reflect.defineMetadata("inject:params",c,e);}}i(N,"Inject");var w=class w{constructor(e){s(this,"request");s(this,"response");s(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};i(w,"PipelineContext");var l=w;var y=class y{constructor(e){s(this,"serviceProvider");s(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(this.isAsyncIterable(r))throw new Error("Handler returned a stream. Use stream() method instead of send().");return r}finally{t.dispose();}}async stream(e){let t=this.serviceProvider.createScope();try{let r=await this.executeHandler(e,t.serviceProvider);if(!this.isAsyncIterable(r))throw new Error("Handler did not return a stream. Use send() method instead of stream().");return r}finally{t.dispose();}}async executeHandler(e,t){let r=t.getService(e.type);if(!r)throw new Error(`No handler registered for request type: ${String(e.type)}`);let a=new l(e);return this.behaviors.length===0?await r.handle(e):await this.executePipeline(a,r,this.behaviors)}async executePipeline(e,t,r){let a=0,c=i(async()=>{if(a<r.length)return await r[a++].handle(e,c);let h=await t.handle(e.request);return e.response=h,h},"next");return await c()}isAsyncIterable(e){return e!=null&&typeof e[Symbol.asyncIterator]=="function"}};i(y,"Mediator");var m=y;var D=class D{handle(e){return this.handleSimple(e)}};i(D,"SimpleHandler");var x=D,P=class P{handle(e){return this.handleStream(e)}};i(P,"StreamingHandler");var I=P;var E=class E{constructor(e){s(this,"type");this.type=e;}};i(E,"BaseCommunicationObject");var p=E;var R=class R extends p{constructor(t){super(t);s(this,"uuid");s(this,"timestamp");this.uuid=v4(),this.timestamp=new Date;}};i(R,"BaseRequest");var b=R;var k=class k extends p{constructor(t){super(t);s(this,"success");s(this,"errors");s(this,"timestamp");this.timestamp=new Date,this.success=true;}setErrors(t){return this.success=false,this.errors=t,this}addError(t){return this.errors||(this.errors=[]),this.errors.push(t),this.success=false,this}};i(k,"BaseResponse");var T=k;var M=class M{constructor(e,t,r){s(this,"serviceProvider");s(this,"mediator");s(this,"isRunning",false);s(this,"adapters");this.serviceProvider=e,this.mediator=t,this.adapters=r;}async run(){if(this.isRunning)throw new Error("Application is already running");for(let e of this.adapters)e.initialize&&await e.initialize(this);this.isRunning=true;}async stop(){if(this.isRunning){for(let e of [...this.adapters].reverse())e.dispose&&await e.dispose();this.isRunning=false;}}async send(e){if(!this.isRunning)throw new Error("Application must be running before sending requests. Call app.run() first.");return this.mediator.send(e)}async stream(e){if(!this.isRunning)throw new Error("Application must be running before streaming requests. Call app.run() first.");return this.mediator.stream(e)}getServiceProvider(){return this.serviceProvider}getMediator(){return this.mediator}get running(){return this.isRunning}};i(M,"Application");var f=M;var B="PipelineBehaviors",C=class C{constructor(){s(this,"services");s(this,"adapters",[]);s(this,"pipelineBehaviors",[]);this.services=new d;}registerHandler(e,t,r=n.Transient){if(typeof t=="function")switch(r){case n.Singleton:this.services.addSingleton(e,t);break;case n.Scoped:this.services.addScoped(e,t);break;case n.Transient:default:this.services.addTransient(e,t);break}else this.services.addSingleton(e,t);return this}registerHandlers(e){return e.forEach((t,r)=>{this.registerHandler(r,t);}),this}registerBehavior(e){return this.pipelineBehaviors.push(e),this}registerSingleton(e,t){return this.services.addSingleton(e,t),this}registerScoped(e,t){return this.services.addScoped(e,t),this}registerTransient(e,t){return this.services.addTransient(e,t),this}registerFactory(e,t,r=n.Transient){return this.services.addFactory(e,t,r),this}use(e){return this.adapters.push(e),this}getServiceCollection(){return this.services}async build(){for(let r of this.adapters)await r.configure(this.services);this.pipelineBehaviors.length>0&&this.services.addSingleton(B,this.pipelineBehaviors.map(r=>typeof r=="function"?new r:r));let e=this.services.buildServiceProvider(),t=new m(e);return new f(e,t,this.adapters)}};i(C,"ApplicationBuilder");var j=C;export{f as Application,j as ApplicationBuilder,p as BaseCommunicationObject,b as BaseRequest,T as BaseResponse,N as Inject,m as Mediator,l as PipelineContext,d as ServiceCollection,n as ServiceLifetime,u as ServiceProvider,x as SimpleHandler,I as StreamingHandler};
@@ -1,6 +1,6 @@
1
- import { a as BaseRequest, b as BaseResponse, I as IRequestHandler } from '../IRequestHandler-CjLrozYA.mjs';
2
- export { H as HandlerResult } from '../IRequestHandler-CjLrozYA.mjs';
3
- export { M as Mediator } from '../Mediator-CF-4m1QF.mjs';
1
+ import { a as BaseRequest, b as BaseResponse, I as IRequestHandler } from '../IRequestHandler-D8MPY7jr.mjs';
2
+ export { H as HandlerResult } from '../IRequestHandler-D8MPY7jr.mjs';
3
+ export { M as Mediator } from '../Mediator-DHJ4zHMn.mjs';
4
4
  import '../ServiceProvider-BcW9XXlN.mjs';
5
5
 
6
6
  declare abstract class SimpleHandler<TRequest extends BaseRequest, TResponse extends BaseResponse> implements IRequestHandler<TRequest, TResponse> {
@@ -1,6 +1,6 @@
1
- import { a as BaseRequest, b as BaseResponse, I as IRequestHandler } from '../IRequestHandler-CjLrozYA.js';
2
- export { H as HandlerResult } from '../IRequestHandler-CjLrozYA.js';
3
- export { M as Mediator } from '../Mediator-DkYg4E8y.js';
1
+ import { a as BaseRequest, b as BaseResponse, I as IRequestHandler } from '../IRequestHandler-D8MPY7jr.js';
2
+ export { H as HandlerResult } from '../IRequestHandler-D8MPY7jr.js';
3
+ export { M as Mediator } from '../Mediator-D3eBV427.js';
4
4
  import '../ServiceProvider-BcW9XXlN.js';
5
5
 
6
6
  declare abstract class SimpleHandler<TRequest extends BaseRequest, TResponse extends BaseResponse> implements IRequestHandler<TRequest, TResponse> {
@@ -1,2 +1,2 @@
1
1
  'use strict';/* conduit - MIT License */
2
- var g=Object.defineProperty;var x=(s,e,t)=>e in s?g(s,e,{enumerable:true,configurable:true,writable:true,value:t}):s[e]=t;var r=(s,e)=>g(s,"name",{value:e,configurable:true});var a=(s,e,t)=>x(s,typeof e!="symbol"?e+"":e,t);var o=class o{constructor(e){a(this,"request");a(this,"response");a(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};r(o,"PipelineContext");var n=o;var c=class c{constructor(e){a(this,"serviceProvider");a(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let i=new n(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(i,t,this.behaviors)}async executePipeline(e,t,i){let u=0,w=r(async()=>{if(u<i.length)return await i[u++].handle(e,w);let f=await t.handle(e.request);return e.response=f,f},"next");return await w()}};r(c,"Mediator");var h=c;var v=class v{handle(e){return this.handleSimple(e)}};r(v,"SimpleHandler");var d=v,p=class p{handle(e){return this.handleStream(e)}};r(p,"StreamingHandler");var l=p;exports.Mediator=h;exports.SimpleHandler=d;exports.StreamingHandler=l;
2
+ var m=Object.defineProperty;var w=(a,e,r)=>e in a?m(a,e,{enumerable:true,configurable:true,writable:true,value:r}):a[e]=r;var s=(a,e)=>m(a,"name",{value:e,configurable:true});var i=(a,e,r)=>w(a,typeof e!="symbol"?e+"":e,r);var c=class c{constructor(e){i(this,"request");i(this,"response");i(this,"metadata",new Map);this.request=e;}setMetadata(e,r){this.metadata.set(e,r);}getMetadata(e){return this.metadata.get(e)}};s(c,"PipelineContext");var o=c;var d=class d{constructor(e){i(this,"serviceProvider");i(this,"behaviors",[]);this.serviceProvider=e;let r=this.serviceProvider.getService("PipelineBehaviors");r&&(this.behaviors=r);}async send(e){let r=this.serviceProvider.createScope();try{let t=await this.executeHandler(e,r.serviceProvider);if(this.isAsyncIterable(t))throw new Error("Handler returned a stream. Use stream() method instead of send().");return t}finally{r.dispose();}}async stream(e){let r=this.serviceProvider.createScope();try{let t=await this.executeHandler(e,r.serviceProvider);if(!this.isAsyncIterable(t))throw new Error("Handler did not return a stream. Use send() method instead of stream().");return t}finally{r.dispose();}}async executeHandler(e,r){let t=r.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let n=new o(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(n,t,this.behaviors)}async executePipeline(e,r,t){let n=0,y=s(async()=>{if(n<t.length)return await t[n++].handle(e,y);let f=await r.handle(e.request);return e.response=f,f},"next");return await y()}isAsyncIterable(e){return e!=null&&typeof e[Symbol.asyncIterator]=="function"}};s(d,"Mediator");var h=d;var v=class v{handle(e){return this.handleSimple(e)}};s(v,"SimpleHandler");var l=v,p=class p{handle(e){return this.handleStream(e)}};s(p,"StreamingHandler");var u=p;exports.Mediator=h;exports.SimpleHandler=l;exports.StreamingHandler=u;
@@ -1,2 +1,2 @@
1
1
  /* conduit - MIT License */
2
- var g=Object.defineProperty;var x=(s,e,t)=>e in s?g(s,e,{enumerable:true,configurable:true,writable:true,value:t}):s[e]=t;var r=(s,e)=>g(s,"name",{value:e,configurable:true});var a=(s,e,t)=>x(s,typeof e!="symbol"?e+"":e,t);var o=class o{constructor(e){a(this,"request");a(this,"response");a(this,"metadata",new Map);this.request=e;}setMetadata(e,t){this.metadata.set(e,t);}getMetadata(e){return this.metadata.get(e)}};r(o,"PipelineContext");var n=o;var c=class c{constructor(e){a(this,"serviceProvider");a(this,"behaviors",[]);this.serviceProvider=e;let t=this.serviceProvider.getService("PipelineBehaviors");t&&(this.behaviors=t);}async send(e){let t=this.serviceProvider.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let i=new n(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(i,t,this.behaviors)}async executePipeline(e,t,i){let u=0,w=r(async()=>{if(u<i.length)return await i[u++].handle(e,w);let f=await t.handle(e.request);return e.response=f,f},"next");return await w()}};r(c,"Mediator");var h=c;var v=class v{handle(e){return this.handleSimple(e)}};r(v,"SimpleHandler");var d=v,p=class p{handle(e){return this.handleStream(e)}};r(p,"StreamingHandler");var l=p;export{h as Mediator,d as SimpleHandler,l as StreamingHandler};
2
+ var m=Object.defineProperty;var w=(a,e,r)=>e in a?m(a,e,{enumerable:true,configurable:true,writable:true,value:r}):a[e]=r;var s=(a,e)=>m(a,"name",{value:e,configurable:true});var i=(a,e,r)=>w(a,typeof e!="symbol"?e+"":e,r);var c=class c{constructor(e){i(this,"request");i(this,"response");i(this,"metadata",new Map);this.request=e;}setMetadata(e,r){this.metadata.set(e,r);}getMetadata(e){return this.metadata.get(e)}};s(c,"PipelineContext");var o=c;var d=class d{constructor(e){i(this,"serviceProvider");i(this,"behaviors",[]);this.serviceProvider=e;let r=this.serviceProvider.getService("PipelineBehaviors");r&&(this.behaviors=r);}async send(e){let r=this.serviceProvider.createScope();try{let t=await this.executeHandler(e,r.serviceProvider);if(this.isAsyncIterable(t))throw new Error("Handler returned a stream. Use stream() method instead of send().");return t}finally{r.dispose();}}async stream(e){let r=this.serviceProvider.createScope();try{let t=await this.executeHandler(e,r.serviceProvider);if(!this.isAsyncIterable(t))throw new Error("Handler did not return a stream. Use send() method instead of stream().");return t}finally{r.dispose();}}async executeHandler(e,r){let t=r.getService(e.type);if(!t)throw new Error(`No handler registered for request type: ${String(e.type)}`);let n=new o(e);return this.behaviors.length===0?await t.handle(e):await this.executePipeline(n,t,this.behaviors)}async executePipeline(e,r,t){let n=0,y=s(async()=>{if(n<t.length)return await t[n++].handle(e,y);let f=await r.handle(e.request);return e.response=f,f},"next");return await y()}isAsyncIterable(e){return e!=null&&typeof e[Symbol.asyncIterator]=="function"}};s(d,"Mediator");var h=d;var v=class v{handle(e){return this.handleSimple(e)}};s(v,"SimpleHandler");var l=v,p=class p{handle(e){return this.handleStream(e)}};s(p,"StreamingHandler");var u=p;export{h as Mediator,l as SimpleHandler,u as StreamingHandler};
@@ -1,17 +1,17 @@
1
- import { a as BaseRequest, b as BaseResponse, H as HandlerResult } from '../IRequestHandler-CjLrozYA.mjs';
1
+ import { a as BaseRequest, b as BaseResponse, H as HandlerResult } from '../IRequestHandler-D8MPY7jr.mjs';
2
2
 
3
- declare class PipelineContext<TRequest extends BaseRequest, TResponse extends BaseResponse> {
4
- readonly request: TRequest;
5
- response?: AsyncIterable<TResponse> | TResponse;
3
+ declare class PipelineContext {
4
+ readonly request: BaseRequest;
5
+ response?: AsyncIterable<BaseResponse> | BaseResponse;
6
6
  metadata: Map<string, any>;
7
- constructor(request: TRequest);
7
+ constructor(request: BaseRequest);
8
8
  setMetadata(key: string, value: any): void;
9
9
  getMetadata<T>(key: string): T | undefined;
10
10
  }
11
11
 
12
- type PipelineDelegate<TResponse> = () => HandlerResult<TResponse>;
13
- interface IPipelineBehavior<TRequest extends BaseRequest, TResponse extends BaseResponse> {
14
- handle(context: PipelineContext<TRequest, TResponse>, next: PipelineDelegate<TResponse>): HandlerResult<TResponse>;
12
+ type PipelineDelegate = () => HandlerResult<BaseResponse>;
13
+ interface IPipelineBehavior {
14
+ handle(context: PipelineContext, next: PipelineDelegate): HandlerResult<BaseResponse>;
15
15
  }
16
16
 
17
17
  export { type IPipelineBehavior, PipelineContext, type PipelineDelegate };
@@ -1,17 +1,17 @@
1
- import { a as BaseRequest, b as BaseResponse, H as HandlerResult } from '../IRequestHandler-CjLrozYA.js';
1
+ import { a as BaseRequest, b as BaseResponse, H as HandlerResult } from '../IRequestHandler-D8MPY7jr.js';
2
2
 
3
- declare class PipelineContext<TRequest extends BaseRequest, TResponse extends BaseResponse> {
4
- readonly request: TRequest;
5
- response?: AsyncIterable<TResponse> | TResponse;
3
+ declare class PipelineContext {
4
+ readonly request: BaseRequest;
5
+ response?: AsyncIterable<BaseResponse> | BaseResponse;
6
6
  metadata: Map<string, any>;
7
- constructor(request: TRequest);
7
+ constructor(request: BaseRequest);
8
8
  setMetadata(key: string, value: any): void;
9
9
  getMetadata<T>(key: string): T | undefined;
10
10
  }
11
11
 
12
- type PipelineDelegate<TResponse> = () => HandlerResult<TResponse>;
13
- interface IPipelineBehavior<TRequest extends BaseRequest, TResponse extends BaseResponse> {
14
- handle(context: PipelineContext<TRequest, TResponse>, next: PipelineDelegate<TResponse>): HandlerResult<TResponse>;
12
+ type PipelineDelegate = () => HandlerResult<BaseResponse>;
13
+ interface IPipelineBehavior {
14
+ handle(context: PipelineContext, next: PipelineDelegate): HandlerResult<BaseResponse>;
15
15
  }
16
16
 
17
17
  export { type IPipelineBehavior, PipelineContext, type PipelineDelegate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oldzy/conduit",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Transport-agnostic request/response pipeline framework with mediator pattern, dependency injection, and middleware support",
5
5
  "author": "oldzy",
6
6
  "license": "MIT",
@@ -1,12 +0,0 @@
1
- import { S as ServiceProvider } from './ServiceProvider-BcW9XXlN.mjs';
2
- import { a as BaseRequest, H as HandlerResult, b as BaseResponse } from './IRequestHandler-CjLrozYA.mjs';
3
-
4
- declare class Mediator {
5
- private serviceProvider;
6
- private behaviors;
7
- constructor(serviceProvider: ServiceProvider);
8
- send(request: BaseRequest): HandlerResult<BaseResponse>;
9
- private executePipeline;
10
- }
11
-
12
- export { Mediator as M };
@@ -1,12 +0,0 @@
1
- import { S as ServiceProvider } from './ServiceProvider-BcW9XXlN.js';
2
- import { a as BaseRequest, H as HandlerResult, b as BaseResponse } from './IRequestHandler-CjLrozYA.js';
3
-
4
- declare class Mediator {
5
- private serviceProvider;
6
- private behaviors;
7
- constructor(serviceProvider: ServiceProvider);
8
- send(request: BaseRequest): HandlerResult<BaseResponse>;
9
- private executePipeline;
10
- }
11
-
12
- export { Mediator as M };