@oldzy/conduit 1.0.2 → 1.0.4
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 +709 -6
- package/dist/{IRequestHandler-CjLrozYA.d.mts → IRequestHandler-x0c3xSqH.d.mts} +2 -3
- package/dist/{IRequestHandler-CjLrozYA.d.ts → IRequestHandler-x0c3xSqH.d.ts} +2 -3
- package/dist/Mediator-CBq5EqK5.d.mts +15 -0
- package/dist/Mediator-CnBmWM_n.d.ts +15 -0
- package/dist/application/index.d.mts +5 -4
- package/dist/application/index.d.ts +5 -4
- package/dist/application/index.js +1 -1
- package/dist/application/index.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/mediator/index.d.mts +3 -3
- package/dist/mediator/index.d.ts +3 -3
- package/dist/mediator/index.js +1 -1
- package/dist/mediator/index.mjs +1 -1
- package/dist/pipeline/index.d.mts +8 -8
- package/dist/pipeline/index.d.ts +8 -8
- package/package.json +3 -2
- package/dist/Mediator-CF-4m1QF.d.mts +0 -12
- package/dist/Mediator-DkYg4E8y.d.ts +0 -12
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
|
|
8
|
-
- 💉 Built-in
|
|
9
|
-
- 🔧
|
|
10
|
-
- 🚀 Transport-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
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
|
|
@@ -6,15 +6,14 @@ declare abstract class BaseCommunicationObject {
|
|
|
6
6
|
declare abstract class BaseRequest extends BaseCommunicationObject {
|
|
7
7
|
readonly uuid: string;
|
|
8
8
|
readonly timestamp: Date;
|
|
9
|
-
constructor(type: string);
|
|
9
|
+
constructor(type: string | symbol);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
declare abstract class BaseResponse extends BaseCommunicationObject {
|
|
13
13
|
success: boolean;
|
|
14
14
|
errors?: string[];
|
|
15
15
|
readonly timestamp: Date;
|
|
16
|
-
|
|
17
|
-
constructor(type: string, requestUuid: string);
|
|
16
|
+
constructor(type: string | symbol);
|
|
18
17
|
setErrors(errors: string[]): this;
|
|
19
18
|
addError(error: string): this;
|
|
20
19
|
}
|
|
@@ -6,15 +6,14 @@ declare abstract class BaseCommunicationObject {
|
|
|
6
6
|
declare abstract class BaseRequest extends BaseCommunicationObject {
|
|
7
7
|
readonly uuid: string;
|
|
8
8
|
readonly timestamp: Date;
|
|
9
|
-
constructor(type: string);
|
|
9
|
+
constructor(type: string | symbol);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
declare abstract class BaseResponse extends BaseCommunicationObject {
|
|
13
13
|
success: boolean;
|
|
14
14
|
errors?: string[];
|
|
15
15
|
readonly timestamp: Date;
|
|
16
|
-
|
|
17
|
-
constructor(type: string, requestUuid: string);
|
|
16
|
+
constructor(type: string | symbol);
|
|
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.mjs';
|
|
2
|
+
import { b as BaseResponse, a as BaseRequest } from './IRequestHandler-x0c3xSqH.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 };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { S as ServiceProvider } from './ServiceProvider-BcW9XXlN.js';
|
|
2
|
+
import { b as BaseResponse, a as BaseRequest } from './IRequestHandler-x0c3xSqH.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 };
|
|
@@ -1,8 +1,8 @@
|
|
|
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,
|
|
3
|
+
import { b as BaseResponse, a as BaseRequest, I as IRequestHandler } from '../IRequestHandler-x0c3xSqH.mjs';
|
|
4
4
|
import { IPipelineBehavior } from '../pipeline/index.mjs';
|
|
5
|
-
import { M as Mediator } from '../Mediator-
|
|
5
|
+
import { M as Mediator } from '../Mediator-CBq5EqK5.mjs';
|
|
6
6
|
|
|
7
7
|
interface IApplicationAdapter {
|
|
8
8
|
readonly name: string;
|
|
@@ -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):
|
|
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
|
|
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,8 +1,8 @@
|
|
|
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,
|
|
3
|
+
import { b as BaseResponse, a as BaseRequest, I as IRequestHandler } from '../IRequestHandler-x0c3xSqH.js';
|
|
4
4
|
import { IPipelineBehavior } from '../pipeline/index.js';
|
|
5
|
-
import { M as Mediator } from '../Mediator-
|
|
5
|
+
import { M as Mediator } from '../Mediator-CnBmWM_n.js';
|
|
6
6
|
|
|
7
7
|
interface IApplicationAdapter {
|
|
8
8
|
readonly name: string;
|
|
@@ -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):
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
5
|
-
export { M as Mediator } from './Mediator-
|
|
4
|
+
export { B as BaseCommunicationObject, a as BaseRequest, b as BaseResponse, H as HandlerResult, I as IRequestHandler } from './IRequestHandler-x0c3xSqH.mjs';
|
|
5
|
+
export { M as Mediator } from './Mediator-CBq5EqK5.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-
|
|
5
|
-
export { M as Mediator } from './Mediator-
|
|
4
|
+
export { B as BaseCommunicationObject, a as BaseRequest, b as BaseResponse, H as HandlerResult, I as IRequestHandler } from './IRequestHandler-x0c3xSqH.js';
|
|
5
|
+
export { M as Mediator } from './Mediator-CnBmWM_n.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
|
|
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
|
|
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-
|
|
2
|
-
export { H as HandlerResult } from '../IRequestHandler-
|
|
3
|
-
export { M as Mediator } from '../Mediator-
|
|
1
|
+
import { a as BaseRequest, b as BaseResponse, I as IRequestHandler } from '../IRequestHandler-x0c3xSqH.mjs';
|
|
2
|
+
export { H as HandlerResult } from '../IRequestHandler-x0c3xSqH.mjs';
|
|
3
|
+
export { M as Mediator } from '../Mediator-CBq5EqK5.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> {
|
package/dist/mediator/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as BaseRequest, b as BaseResponse, I as IRequestHandler } from '../IRequestHandler-
|
|
2
|
-
export { H as HandlerResult } from '../IRequestHandler-
|
|
3
|
-
export { M as Mediator } from '../Mediator-
|
|
1
|
+
import { a as BaseRequest, b as BaseResponse, I as IRequestHandler } from '../IRequestHandler-x0c3xSqH.js';
|
|
2
|
+
export { H as HandlerResult } from '../IRequestHandler-x0c3xSqH.js';
|
|
3
|
+
export { M as Mediator } from '../Mediator-CnBmWM_n.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> {
|
package/dist/mediator/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use strict';/* conduit - MIT License */
|
|
2
|
-
var
|
|
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;
|
package/dist/mediator/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/* conduit - MIT License */
|
|
2
|
-
var
|
|
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-
|
|
1
|
+
import { a as BaseRequest, b as BaseResponse, H as HandlerResult } from '../IRequestHandler-x0c3xSqH.mjs';
|
|
2
2
|
|
|
3
|
-
declare class PipelineContext
|
|
4
|
-
readonly request:
|
|
5
|
-
response?: AsyncIterable<
|
|
3
|
+
declare class PipelineContext {
|
|
4
|
+
readonly request: BaseRequest;
|
|
5
|
+
response?: AsyncIterable<BaseResponse> | BaseResponse;
|
|
6
6
|
metadata: Map<string, any>;
|
|
7
|
-
constructor(request:
|
|
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
|
|
13
|
-
interface IPipelineBehavior
|
|
14
|
-
handle(context: PipelineContext
|
|
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/dist/pipeline/index.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { a as BaseRequest, b as BaseResponse, H as HandlerResult } from '../IRequestHandler-
|
|
1
|
+
import { a as BaseRequest, b as BaseResponse, H as HandlerResult } from '../IRequestHandler-x0c3xSqH.js';
|
|
2
2
|
|
|
3
|
-
declare class PipelineContext
|
|
4
|
-
readonly request:
|
|
5
|
-
response?: AsyncIterable<
|
|
3
|
+
declare class PipelineContext {
|
|
4
|
+
readonly request: BaseRequest;
|
|
5
|
+
response?: AsyncIterable<BaseResponse> | BaseResponse;
|
|
6
6
|
metadata: Map<string, any>;
|
|
7
|
-
constructor(request:
|
|
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
|
|
13
|
-
interface IPipelineBehavior
|
|
14
|
-
handle(context: PipelineContext
|
|
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.
|
|
3
|
+
"version": "1.0.4",
|
|
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",
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"test:coverage": "vitest --coverage",
|
|
52
52
|
"test:watch": "vitest --watch",
|
|
53
53
|
"lint": "eslint src",
|
|
54
|
-
"prepublishOnly": "npm run build:prod && npm test"
|
|
54
|
+
"prepublishOnly": "npm run build:prod && npm test",
|
|
55
|
+
"publish:npm": "npm run build:prod && npm test && npm publish --access public"
|
|
55
56
|
},
|
|
56
57
|
"keywords": [
|
|
57
58
|
"mediator",
|
|
@@ -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 };
|