@adaas/a-utils 0.1.13 → 0.1.15

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.
@@ -0,0 +1,518 @@
1
+ /**
2
+ * A-Channel Examples
3
+ *
4
+ * This file contains practical examples of using A-Channel for various communication scenarios.
5
+ * Run with: npx ts-node examples/channel-examples.ts
6
+ */
7
+
8
+ import { A_Channel } from '../src/lib/A-Channel/A-Channel.component';
9
+ import { A_ChannelFeatures } from '../src/lib/A-Channel/A-Channel.constants';
10
+ import { A_ChannelRequest } from '../src/lib/A-Channel/A-ChannelRequest.context';
11
+ import { A_Component, A_Context, A_Feature, A_Inject } from '@adaas/a-concept';
12
+
13
+ // Example 1: Basic Channel Usage
14
+ async function basicChannelExample() {
15
+ console.log('\n=== Basic Channel Example ===');
16
+
17
+ const channel = new A_Channel();
18
+ A_Context.root.register(channel);
19
+
20
+ // Initialize the channel
21
+ await channel.initialize;
22
+ console.log(`Channel initialized, processing: ${channel.processing}`);
23
+
24
+ // Send a request
25
+ const response = await channel.request({
26
+ action: 'greet',
27
+ name: 'World'
28
+ });
29
+
30
+ console.log('Request params:', response.params);
31
+ console.log('Request status:', response.status);
32
+ }
33
+
34
+ // Example 2: HTTP Client Channel
35
+ interface HttpRequest {
36
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
37
+ url: string;
38
+ headers?: Record<string, string>;
39
+ body?: any;
40
+ }
41
+
42
+ interface HttpResponse {
43
+ status: number;
44
+ statusText: string;
45
+ data: any;
46
+ headers: Record<string, string>;
47
+ }
48
+
49
+ class HttpChannel extends A_Channel {}
50
+
51
+ class HttpProcessor extends A_Component {
52
+
53
+ @A_Feature.Extend({ scope: [HttpChannel] })
54
+ async [A_ChannelFeatures.onConnect]() {
55
+ console.log('HTTP Channel connected - ready to make requests');
56
+ }
57
+
58
+ @A_Feature.Extend({ scope: [HttpChannel] })
59
+ async [A_ChannelFeatures.onBeforeRequest](
60
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<HttpRequest>
61
+ ) {
62
+ const { method, url } = context.params;
63
+ console.log(`Preparing ${method} request to ${url}`);
64
+
65
+ // Validate URL
66
+ if (!url || !url.startsWith('http')) {
67
+ throw new Error('Invalid URL provided');
68
+ }
69
+ }
70
+
71
+ @A_Feature.Extend({ scope: [HttpChannel] })
72
+ async [A_ChannelFeatures.onRequest](
73
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<HttpRequest, HttpResponse>
74
+ ) {
75
+ const { method, url, headers, body } = context.params;
76
+
77
+ console.log(`Making ${method} request to ${url}`);
78
+
79
+ // Simulate HTTP request (in real implementation, use fetch or axios)
80
+ await new Promise(resolve => setTimeout(resolve, 100)); // Simulate network delay
81
+
82
+ const mockResponse: HttpResponse = {
83
+ status: 200,
84
+ statusText: 'OK',
85
+ data: {
86
+ success: true,
87
+ method,
88
+ url,
89
+ timestamp: new Date().toISOString()
90
+ },
91
+ headers: {
92
+ 'content-type': 'application/json',
93
+ 'x-response-time': '100ms'
94
+ }
95
+ };
96
+
97
+ (context as any)._result = mockResponse;
98
+ }
99
+
100
+ @A_Feature.Extend({ scope: [HttpChannel] })
101
+ async [A_ChannelFeatures.onAfterRequest](
102
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<HttpRequest, HttpResponse>
103
+ ) {
104
+ const response = context.data;
105
+ console.log(`Request completed with status: ${response?.status}`);
106
+ }
107
+
108
+ @A_Feature.Extend({ scope: [HttpChannel] })
109
+ async [A_ChannelFeatures.onError](
110
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<HttpRequest>
111
+ ) {
112
+ console.error(`HTTP request failed for ${context.params.method} ${context.params.url}`);
113
+ }
114
+ }
115
+
116
+ async function httpChannelExample() {
117
+ console.log('\n=== HTTP Channel Example ===');
118
+
119
+ A_Context.reset();
120
+ A_Context.root.register(HttpProcessor);
121
+
122
+ const httpChannel = new HttpChannel();
123
+ A_Context.root.register(httpChannel);
124
+
125
+ // Make GET request
126
+ const getResponse = await httpChannel.request<HttpRequest, HttpResponse>({
127
+ method: 'GET',
128
+ url: 'https://api.example.com/users'
129
+ });
130
+
131
+ console.log('GET Response:', getResponse.data);
132
+
133
+ // Make POST request
134
+ const postResponse = await httpChannel.request<HttpRequest, HttpResponse>({
135
+ method: 'POST',
136
+ url: 'https://api.example.com/users',
137
+ body: { name: 'John Doe', email: 'john@example.com' }
138
+ });
139
+
140
+ console.log('POST Response:', postResponse.data);
141
+ }
142
+
143
+ // Example 3: Event Broadcasting Channel
144
+ interface EventMessage {
145
+ eventType: string;
146
+ payload: any;
147
+ recipients: string[];
148
+ priority?: 'low' | 'normal' | 'high';
149
+ }
150
+
151
+ class EventChannel extends A_Channel {}
152
+
153
+ class EventBroadcaster extends A_Component {
154
+
155
+ @A_Feature.Extend({ scope: [EventChannel] })
156
+ async [A_ChannelFeatures.onConnect]() {
157
+ console.log('Event Broadcasting Channel connected');
158
+ }
159
+
160
+ @A_Feature.Extend({ scope: [EventChannel] })
161
+ async [A_ChannelFeatures.onSend](
162
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<EventMessage>
163
+ ) {
164
+ const { eventType, payload, recipients, priority = 'normal' } = context.params;
165
+
166
+ console.log(`Broadcasting ${eventType} event to ${recipients.length} recipients`);
167
+ console.log(`Priority: ${priority}`);
168
+
169
+ // Simulate broadcasting to each recipient
170
+ for (const recipient of recipients) {
171
+ await new Promise(resolve => setTimeout(resolve, 50)); // Simulate send delay
172
+ console.log(`āœ“ Sent to ${recipient}`);
173
+ }
174
+
175
+ console.log(`Event ${eventType} broadcast completed`);
176
+ }
177
+
178
+ @A_Feature.Extend({ scope: [EventChannel] })
179
+ async [A_ChannelFeatures.onError](
180
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<EventMessage>
181
+ ) {
182
+ console.error(`Failed to broadcast event: ${context.params.eventType}`);
183
+ }
184
+ }
185
+
186
+ async function eventChannelExample() {
187
+ console.log('\n=== Event Broadcasting Channel Example ===');
188
+
189
+ A_Context.reset();
190
+ A_Context.root.register(EventBroadcaster);
191
+
192
+ const eventChannel = new EventChannel();
193
+ A_Context.root.register(eventChannel);
194
+
195
+ // Broadcast user login event
196
+ await eventChannel.send({
197
+ eventType: 'user.login',
198
+ payload: {
199
+ userId: 'user-123',
200
+ loginTime: new Date().toISOString(),
201
+ ipAddress: '192.168.1.1'
202
+ },
203
+ recipients: ['admin@example.com', 'security@example.com'],
204
+ priority: 'normal'
205
+ });
206
+
207
+ // Broadcast critical alert
208
+ await eventChannel.send({
209
+ eventType: 'system.alert',
210
+ payload: {
211
+ severity: 'critical',
212
+ message: 'Database connection lost',
213
+ timestamp: new Date().toISOString()
214
+ },
215
+ recipients: ['ops@example.com', 'admin@example.com', 'oncall@example.com'],
216
+ priority: 'high'
217
+ });
218
+ }
219
+
220
+ // Example 4: Database Channel with Connection Pooling
221
+ interface DatabaseQuery {
222
+ operation: 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE';
223
+ table: string;
224
+ where?: Record<string, any>;
225
+ data?: Record<string, any>;
226
+ limit?: number;
227
+ }
228
+
229
+ interface DatabaseResult {
230
+ success: boolean;
231
+ rowsAffected: number;
232
+ data?: any[];
233
+ insertId?: number;
234
+ executionTime: number;
235
+ }
236
+
237
+ class DatabaseChannel extends A_Channel {
238
+ private connectionPool: Array<{ id: string; busy: boolean }> = [];
239
+
240
+ getAvailableConnection() {
241
+ return this.connectionPool.find(conn => !conn.busy);
242
+ }
243
+
244
+ getPoolStats() {
245
+ return {
246
+ total: this.connectionPool.length,
247
+ busy: this.connectionPool.filter(conn => conn.busy).length,
248
+ available: this.connectionPool.filter(conn => !conn.busy).length
249
+ };
250
+ }
251
+ }
252
+
253
+ class DatabaseProcessor extends A_Component {
254
+
255
+ @A_Feature.Extend({ scope: [DatabaseChannel] })
256
+ async [A_ChannelFeatures.onConnect]() {
257
+ const channel = A_Context.scope(this).resolve(DatabaseChannel);
258
+
259
+ // Initialize connection pool
260
+ for (let i = 0; i < 5; i++) {
261
+ channel['connectionPool'].push({
262
+ id: `conn-${i}`,
263
+ busy: false
264
+ });
265
+ }
266
+
267
+ console.log('Database Channel connected with 5 connections in pool');
268
+ }
269
+
270
+ @A_Feature.Extend({ scope: [DatabaseChannel] })
271
+ async [A_ChannelFeatures.onBeforeRequest](
272
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<DatabaseQuery>
273
+ ) {
274
+ const channel = A_Context.scope(this).resolve(DatabaseChannel);
275
+ const { operation, table } = context.params;
276
+
277
+ console.log(`Executing ${operation} on table ${table}`);
278
+
279
+ // Check for available connection
280
+ const availableConn = channel.getAvailableConnection();
281
+ if (!availableConn) {
282
+ throw new Error('No available database connections');
283
+ }
284
+
285
+ // Reserve connection
286
+ availableConn.busy = true;
287
+ (context as any)._connection = availableConn;
288
+
289
+ console.log(`Using connection: ${availableConn.id}`);
290
+ console.log('Pool stats:', channel.getPoolStats());
291
+ }
292
+
293
+ @A_Feature.Extend({ scope: [DatabaseChannel] })
294
+ async [A_ChannelFeatures.onRequest](
295
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<DatabaseQuery, DatabaseResult>
296
+ ) {
297
+ const { operation, table, where, data, limit } = context.params;
298
+ const startTime = Date.now();
299
+
300
+ // Simulate database operation
301
+ await new Promise(resolve => setTimeout(resolve, Math.random() * 200 + 50));
302
+
303
+ const executionTime = Date.now() - startTime;
304
+ let result: DatabaseResult;
305
+
306
+ switch (operation) {
307
+ case 'SELECT':
308
+ result = {
309
+ success: true,
310
+ rowsAffected: 0,
311
+ data: [
312
+ { id: 1, name: 'John Doe', email: 'john@example.com' },
313
+ { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
314
+ ].slice(0, limit || 10),
315
+ executionTime
316
+ };
317
+ break;
318
+
319
+ case 'INSERT':
320
+ result = {
321
+ success: true,
322
+ rowsAffected: 1,
323
+ insertId: Math.floor(Math.random() * 1000) + 1,
324
+ executionTime
325
+ };
326
+ break;
327
+
328
+ case 'UPDATE':
329
+ case 'DELETE':
330
+ result = {
331
+ success: true,
332
+ rowsAffected: Math.floor(Math.random() * 5) + 1,
333
+ executionTime
334
+ };
335
+ break;
336
+
337
+ default:
338
+ throw new Error(`Unsupported operation: ${operation}`);
339
+ }
340
+
341
+ (context as any)._result = result;
342
+ }
343
+
344
+ @A_Feature.Extend({ scope: [DatabaseChannel] })
345
+ async [A_ChannelFeatures.onAfterRequest](
346
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<DatabaseQuery, DatabaseResult>
347
+ ) {
348
+ // Release connection
349
+ const connection = (context as any)._connection;
350
+ if (connection) {
351
+ connection.busy = false;
352
+ console.log(`Released connection: ${connection.id}`);
353
+ }
354
+
355
+ const result = context.data;
356
+ console.log(`Query completed in ${result?.executionTime}ms, affected ${result?.rowsAffected} rows`);
357
+ }
358
+
359
+ @A_Feature.Extend({ scope: [DatabaseChannel] })
360
+ async [A_ChannelFeatures.onError](
361
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest<DatabaseQuery>
362
+ ) {
363
+ // Release connection on error
364
+ const connection = (context as any)._connection;
365
+ if (connection) {
366
+ connection.busy = false;
367
+ console.log(`Released connection after error: ${connection.id}`);
368
+ }
369
+
370
+ console.error(`Database operation failed: ${context.params.operation} on ${context.params.table}`);
371
+ }
372
+ }
373
+
374
+ async function databaseChannelExample() {
375
+ console.log('\n=== Database Channel Example ===');
376
+
377
+ A_Context.reset();
378
+ A_Context.root.register(DatabaseProcessor);
379
+
380
+ const dbChannel = new DatabaseChannel();
381
+ A_Context.root.register(dbChannel);
382
+
383
+ // Execute multiple queries concurrently
384
+ const queries = [
385
+ dbChannel.request<DatabaseQuery, DatabaseResult>({
386
+ operation: 'SELECT',
387
+ table: 'users',
388
+ where: { active: true },
389
+ limit: 10
390
+ }),
391
+
392
+ dbChannel.request<DatabaseQuery, DatabaseResult>({
393
+ operation: 'INSERT',
394
+ table: 'users',
395
+ data: { name: 'Alice Johnson', email: 'alice@example.com' }
396
+ }),
397
+
398
+ dbChannel.request<DatabaseQuery, DatabaseResult>({
399
+ operation: 'UPDATE',
400
+ table: 'users',
401
+ where: { id: 1 },
402
+ data: { lastLogin: new Date().toISOString() }
403
+ })
404
+ ];
405
+
406
+ const results = await Promise.all(queries);
407
+
408
+ results.forEach((result, index) => {
409
+ const operation = ['SELECT', 'INSERT', 'UPDATE'][index];
410
+ console.log(`${operation} result:`, result.data);
411
+ });
412
+
413
+ console.log('Final pool stats:', dbChannel.getPoolStats());
414
+ }
415
+
416
+ // Example 5: Error Handling and Recovery
417
+ class RobustChannel extends A_Channel {}
418
+
419
+ class RobustProcessor extends A_Component {
420
+ private retryCount = new Map<string, number>();
421
+
422
+ @A_Feature.Extend({ scope: [RobustChannel] })
423
+ async [A_ChannelFeatures.onRequest](
424
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest
425
+ ) {
426
+ const { operation, shouldFail } = context.params;
427
+
428
+ if (shouldFail) {
429
+ const errorType = Math.random() > 0.5 ? 'network' : 'timeout';
430
+ throw new Error(`Simulated ${errorType} error`);
431
+ }
432
+
433
+ (context as any)._result = {
434
+ success: true,
435
+ operation,
436
+ processedAt: new Date().toISOString()
437
+ };
438
+ }
439
+
440
+ @A_Feature.Extend({ scope: [RobustChannel] })
441
+ async [A_ChannelFeatures.onError](
442
+ @A_Inject(A_ChannelRequest) context: A_ChannelRequest
443
+ ) {
444
+ const requestId = JSON.stringify(context.params);
445
+ const currentRetries = this.retryCount.get(requestId) || 0;
446
+ const maxRetries = 3;
447
+
448
+ console.log(`Error occurred (attempt ${currentRetries + 1}/${maxRetries + 1}):`, context.failed);
449
+
450
+ if (currentRetries < maxRetries) {
451
+ this.retryCount.set(requestId, currentRetries + 1);
452
+ console.log(`Implementing retry logic for attempt ${currentRetries + 2}`);
453
+ // In a real implementation, you might retry the operation here
454
+ } else {
455
+ console.log('Max retries exceeded, giving up');
456
+ this.retryCount.delete(requestId);
457
+ }
458
+ }
459
+ }
460
+
461
+ async function errorHandlingExample() {
462
+ console.log('\n=== Error Handling and Recovery Example ===');
463
+
464
+ A_Context.reset();
465
+ A_Context.root.register(RobustProcessor);
466
+
467
+ const robustChannel = new RobustChannel();
468
+ A_Context.root.register(robustChannel);
469
+
470
+ // Test successful operation
471
+ const successResult = await robustChannel.request({
472
+ operation: 'process-data',
473
+ shouldFail: false
474
+ });
475
+
476
+ console.log('Success result:', successResult.data);
477
+
478
+ // Test failing operation
479
+ const failResult = await robustChannel.request({
480
+ operation: 'process-data',
481
+ shouldFail: true
482
+ });
483
+
484
+ console.log('Fail result status:', failResult.status);
485
+ console.log('Failed:', failResult.failed);
486
+ }
487
+
488
+ // Run all examples
489
+ async function runAllExamples() {
490
+ console.log('šŸš€ Running A-Channel Examples\n');
491
+
492
+ try {
493
+ await basicChannelExample();
494
+ await httpChannelExample();
495
+ await eventChannelExample();
496
+ await databaseChannelExample();
497
+ await errorHandlingExample();
498
+
499
+ console.log('\nāœ… All A-Channel examples completed successfully!');
500
+ } catch (error) {
501
+ console.error('\nāŒ Example failed:', error);
502
+ }
503
+ }
504
+
505
+ // Export for use as module or run directly
506
+ export {
507
+ basicChannelExample,
508
+ httpChannelExample,
509
+ eventChannelExample,
510
+ databaseChannelExample,
511
+ errorHandlingExample,
512
+ runAllExamples
513
+ };
514
+
515
+ // Run if this file is executed directly
516
+ if (require.main === module) {
517
+ runAllExamples();
518
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaas/a-utils",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "A-Utils is a set of utilities that are used across the ADAAS ecosystem. This package is designed to be a collection of utilities that are used across the ADAAS ecosystem.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -36,19 +36,37 @@
36
36
  },
37
37
  "repository": {
38
38
  "type": "git",
39
- "url": "git+https://github.com/ADAAS-org/adaas-adf-auth.git"
39
+ "url": "git+https://github.com/ADAAS-org/adaas-a-utils.git"
40
40
  },
41
41
  "keywords": [
42
42
  "sdk",
43
+ "utilities",
44
+ "typescript",
45
+ "nodejs",
46
+ "command-pattern",
47
+ "channel",
48
+ "configuration",
49
+ "logging",
50
+ "scheduling",
51
+ "memory-management",
52
+ "dependency-injection",
53
+ "component-architecture",
54
+ "adaas",
55
+ "ecosystem",
43
56
  "ai",
44
- "rag"
57
+ "rag",
58
+ "manifest",
59
+ "polyfill",
60
+ "async",
61
+ "lifecycle",
62
+ "error-handling"
45
63
  ],
46
64
  "author": "adaas.org",
47
65
  "license": "ISC",
48
66
  "bugs": {
49
- "url": "https://github.com/ADAAS-org/adaas-adf-auth/issues"
67
+ "url": "https://github.com/ADAAS-org/adaas-a-utils/issues"
50
68
  },
51
- "homepage": "https://github.com/ADAAS-org/adaas-adf-auth#readme",
69
+ "homepage": "https://github.com/ADAAS-org/adaas-a-utils#readme",
52
70
  "dependencies": {
53
71
  "@adaas/a-concept": "^0.1.24"
54
72
  },
package/src/index.ts CHANGED
@@ -3,8 +3,10 @@
3
3
  // A-Channel Components
4
4
  // ============================================================================
5
5
  export { A_Channel } from './lib/A-Channel/A-Channel.component';
6
+ export { A_ChannelRequest } from './lib/A-Channel/A-ChannelRequest.context';
6
7
  export { A_ChannelError } from './lib/A-Channel/A-Channel.error';
7
- // export * from './src/lib/A-Channel/A-Channel.types'; // Empty file
8
+ export * from './lib/A-Channel/A-Channel.types';
9
+ export * from './lib/A-Channel/A-Channel.constants';
8
10
 
9
11
 
10
12
  // ============================================================================