@adaas/a-utils 0.1.11 → 0.1.13
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 +87 -32
- package/dist/index.d.mts +33 -6
- package/dist/index.d.ts +33 -6
- package/dist/index.js +66 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +66 -12
- package/dist/index.mjs.map +1 -1
- package/examples/command-examples.ts +268 -0
- package/package.json +1 -1
- package/src/lib/A-Command/A-Command.constants.ts +4 -0
- package/src/lib/A-Command/A-Command.entity.ts +74 -15
- package/src/lib/A-Command/A-Command.error.ts +2 -0
- package/src/lib/A-Command/A-Command.types.ts +6 -1
- package/src/lib/A-Command/README.md +645 -0
- package/src/lib/A-Memory/A-Memory.context.ts +15 -0
- package/tests/A-Command.test.ts +447 -2
- package/tests/A-Memory.test.ts +189 -0
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
# A-Command
|
|
2
|
+
|
|
3
|
+
A powerful command pattern implementation that provides structured execution, lifecycle management, event handling, and state persistence for TypeScript applications.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Key Features](#key-features)
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Basic Usage](#basic-usage)
|
|
11
|
+
- [Advanced Usage](#advanced-usage)
|
|
12
|
+
- [Lifecycle Management](#lifecycle-management)
|
|
13
|
+
- [Event System](#event-system)
|
|
14
|
+
- [Serialization & Persistence](#serialization--persistence)
|
|
15
|
+
- [Error Handling](#error-handling)
|
|
16
|
+
- [API Reference](#api-reference)
|
|
17
|
+
- [Examples](#examples)
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
A-Command is an implementation of the Command Pattern that allows you to encapsulate requests as objects, thereby letting you parameterize clients with different requests, queue operations, and support undo operations. It provides a structured approach to handling complex business logic with full lifecycle management and event-driven architecture.
|
|
22
|
+
|
|
23
|
+
## Key Features
|
|
24
|
+
|
|
25
|
+
- 🔄 **Complete Lifecycle Management** - Automatic progression through init → compile → execute → complete/fail phases
|
|
26
|
+
- 📡 **Event-Driven Architecture** - Subscribe to lifecycle events and custom events
|
|
27
|
+
- 💾 **State Persistence** - Full serialization/deserialization support for command state
|
|
28
|
+
- 🎯 **Type Safety** - Full TypeScript support with generic types for parameters and results
|
|
29
|
+
- 🔧 **Extensible** - Component-based architecture for custom execution logic
|
|
30
|
+
- 🛡️ **Error Handling** - Comprehensive error capture and management
|
|
31
|
+
- ⏱️ **Execution Tracking** - Built-in timing and duration tracking
|
|
32
|
+
- 🏗️ **Dependency Injection** - Integration with A-Context for scope management
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install @adaas/a-utils
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Basic Usage
|
|
41
|
+
|
|
42
|
+
### Simple Command Creation and Execution
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { A_Command } from '@adaas/a-utils/lib/A-Command/A-Command.entity';
|
|
46
|
+
import { A_Context } from '@adaas/a-concept';
|
|
47
|
+
|
|
48
|
+
// Create a basic command
|
|
49
|
+
const command = new A_Command({
|
|
50
|
+
action: 'greet',
|
|
51
|
+
name: 'World'
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Register command in context
|
|
55
|
+
A_Context.root.register(command);
|
|
56
|
+
|
|
57
|
+
// Execute the command
|
|
58
|
+
await command.execute();
|
|
59
|
+
|
|
60
|
+
console.log(`Command status: ${command.status}`);
|
|
61
|
+
console.log(`Execution duration: ${command.duration}ms`);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Typed Command with Custom Parameters and Result
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
interface UserCreateParams {
|
|
68
|
+
name: string;
|
|
69
|
+
email: string;
|
|
70
|
+
role: 'admin' | 'user';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface UserCreateResult {
|
|
74
|
+
userId: string;
|
|
75
|
+
createdAt: string;
|
|
76
|
+
profileCreated: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
class CreateUserCommand extends A_Command<UserCreateParams, UserCreateResult> {}
|
|
80
|
+
|
|
81
|
+
const command = new CreateUserCommand({
|
|
82
|
+
name: 'John Doe',
|
|
83
|
+
email: 'john@example.com',
|
|
84
|
+
role: 'user'
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
A_Context.root.register(command);
|
|
88
|
+
await command.execute();
|
|
89
|
+
|
|
90
|
+
// Access typed result
|
|
91
|
+
const result = command.result;
|
|
92
|
+
console.log(`Created user: ${result?.userId}`);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Advanced Usage
|
|
96
|
+
|
|
97
|
+
### Custom Command Logic with Components
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { A_Component, A_Feature, A_Inject } from '@adaas/a-concept';
|
|
101
|
+
import { A_Memory } from '@adaas/a-utils/lib/A-Memory/A-Memory.context';
|
|
102
|
+
import { A_CONSTANTS_A_Command_Features } from '@adaas/a-utils/lib/A-Command/A-Command.constants';
|
|
103
|
+
|
|
104
|
+
// Define command types
|
|
105
|
+
interface OrderProcessParams {
|
|
106
|
+
orderId: string;
|
|
107
|
+
items: Array<{ productId: string; quantity: number }>;
|
|
108
|
+
customerId: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
interface OrderProcessResult {
|
|
112
|
+
orderNumber: string;
|
|
113
|
+
totalAmount: number;
|
|
114
|
+
estimatedDelivery: string;
|
|
115
|
+
paymentProcessed: boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
class ProcessOrderCommand extends A_Command<OrderProcessParams, OrderProcessResult> {}
|
|
119
|
+
|
|
120
|
+
// Create a component with custom execution logic
|
|
121
|
+
class OrderProcessor extends A_Component {
|
|
122
|
+
|
|
123
|
+
@A_Feature.Extend({ scope: [ProcessOrderCommand] })
|
|
124
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
125
|
+
@A_Inject(A_Memory) memory: A_Memory<OrderProcessResult>
|
|
126
|
+
) {
|
|
127
|
+
// Access command parameters through the command instance
|
|
128
|
+
const command = A_Context.scope(this).resolve(ProcessOrderCommand);
|
|
129
|
+
const { orderId, items, customerId } = command.params;
|
|
130
|
+
|
|
131
|
+
// Process the order
|
|
132
|
+
const orderNumber = `ORD-${Date.now()}`;
|
|
133
|
+
const totalAmount = items.reduce((sum, item) => sum + (item.quantity * 10), 0);
|
|
134
|
+
const estimatedDelivery = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
135
|
+
|
|
136
|
+
// Store results in memory
|
|
137
|
+
await memory.set('orderNumber', orderNumber);
|
|
138
|
+
await memory.set('totalAmount', totalAmount);
|
|
139
|
+
await memory.set('estimatedDelivery', estimatedDelivery);
|
|
140
|
+
await memory.set('paymentProcessed', true);
|
|
141
|
+
|
|
142
|
+
console.log(`Processed order ${orderNumber} for customer ${customerId}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Usage
|
|
147
|
+
A_Context.reset();
|
|
148
|
+
A_Context.root.register(OrderProcessor);
|
|
149
|
+
|
|
150
|
+
const command = new ProcessOrderCommand({
|
|
151
|
+
orderId: 'order-123',
|
|
152
|
+
customerId: 'customer-456',
|
|
153
|
+
items: [
|
|
154
|
+
{ productId: 'prod-1', quantity: 2 },
|
|
155
|
+
{ productId: 'prod-2', quantity: 1 }
|
|
156
|
+
]
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
A_Context.root.register(command);
|
|
160
|
+
await command.execute();
|
|
161
|
+
|
|
162
|
+
console.log('Order processed:', command.result);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Lifecycle Management
|
|
166
|
+
|
|
167
|
+
A-Command follows a structured lifecycle with automatic progression through defined phases:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
class LifecycleCommand extends A_Command<{}, {}> {}
|
|
171
|
+
|
|
172
|
+
const command = new LifecycleCommand({});
|
|
173
|
+
A_Context.root.register(command);
|
|
174
|
+
|
|
175
|
+
// Track each lifecycle phase
|
|
176
|
+
console.log('Initial status:', command.status); // CREATED
|
|
177
|
+
|
|
178
|
+
await command.init();
|
|
179
|
+
console.log('After init:', command.status); // INITIALIZED
|
|
180
|
+
|
|
181
|
+
await command.compile();
|
|
182
|
+
console.log('After compile:', command.status); // COMPILED
|
|
183
|
+
|
|
184
|
+
// Execute runs all phases automatically
|
|
185
|
+
await command.execute();
|
|
186
|
+
console.log('After execute:', command.status); // COMPLETED
|
|
187
|
+
|
|
188
|
+
// Access timing information
|
|
189
|
+
console.log('Started at:', command.startedAt);
|
|
190
|
+
console.log('Ended at:', command.endedAt);
|
|
191
|
+
console.log('Duration:', command.duration, 'ms');
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Lifecycle Phases
|
|
195
|
+
|
|
196
|
+
1. **CREATED** - Initial state when command is instantiated
|
|
197
|
+
2. **INITIALIZATION** - Setting up execution scope and dependencies
|
|
198
|
+
3. **INITIALIZED** - Ready for compilation
|
|
199
|
+
4. **COMPILATION** - Preparing execution environment
|
|
200
|
+
5. **COMPILED** - Ready for execution
|
|
201
|
+
6. **COMPLETED** - Successfully finished execution
|
|
202
|
+
7. **FAILED** - Execution failed with errors
|
|
203
|
+
|
|
204
|
+
## Event System
|
|
205
|
+
|
|
206
|
+
### Lifecycle Events
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const command = new A_Command({});
|
|
210
|
+
A_Context.root.register(command);
|
|
211
|
+
|
|
212
|
+
// Subscribe to lifecycle events
|
|
213
|
+
command.on('init', (cmd) => {
|
|
214
|
+
console.log('Command initializing:', cmd?.code);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
command.on('compile', (cmd) => {
|
|
218
|
+
console.log('Command compiling:', cmd?.code);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
command.on('execute', (cmd) => {
|
|
222
|
+
console.log('Command executing:', cmd?.code);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
command.on('complete', (cmd) => {
|
|
226
|
+
console.log('Command completed:', cmd?.code);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
command.on('fail', (cmd) => {
|
|
230
|
+
console.log('Command failed:', cmd?.code);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
await command.execute();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Custom Events
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
type CustomEvents = 'validation-started' | 'data-processed' | 'notification-sent';
|
|
240
|
+
|
|
241
|
+
class CustomEventCommand extends A_Command<{}, {}, CustomEvents> {}
|
|
242
|
+
|
|
243
|
+
const command = new CustomEventCommand({});
|
|
244
|
+
A_Context.root.register(command);
|
|
245
|
+
|
|
246
|
+
// Subscribe to custom events
|
|
247
|
+
command.on('validation-started', (cmd) => {
|
|
248
|
+
console.log('Validation phase started');
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
command.on('data-processed', (cmd) => {
|
|
252
|
+
console.log('Data processing completed');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Emit custom events during execution
|
|
256
|
+
command.emit('validation-started');
|
|
257
|
+
command.emit('data-processed');
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Managing Event Listeners
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const command = new A_Command({});
|
|
264
|
+
A_Context.root.register(command);
|
|
265
|
+
|
|
266
|
+
// Add listener
|
|
267
|
+
const listener = (cmd) => console.log('Event triggered');
|
|
268
|
+
command.on('execute', listener);
|
|
269
|
+
|
|
270
|
+
// Remove listener
|
|
271
|
+
command.off('execute', listener);
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Serialization & Persistence
|
|
275
|
+
|
|
276
|
+
### Basic Serialization
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
const command = new A_Command({
|
|
280
|
+
userId: '12345',
|
|
281
|
+
action: 'update-profile',
|
|
282
|
+
data: { name: 'John Doe', email: 'john@example.com' }
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
A_Context.root.register(command);
|
|
286
|
+
await command.execute();
|
|
287
|
+
|
|
288
|
+
// Serialize command state
|
|
289
|
+
const serialized = command.toJSON();
|
|
290
|
+
console.log('Serialized:', JSON.stringify(serialized, null, 2));
|
|
291
|
+
|
|
292
|
+
// Deserialize and restore command
|
|
293
|
+
const restoredCommand = new A_Command(serialized);
|
|
294
|
+
console.log('Restored params:', restoredCommand.params);
|
|
295
|
+
console.log('Restored status:', restoredCommand.status);
|
|
296
|
+
console.log('Restored result:', restoredCommand.result);
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Cross-Session Persistence
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
// Simulate saving command state to database/storage
|
|
303
|
+
async function saveCommandState(command: A_Command) {
|
|
304
|
+
const serialized = command.toJSON();
|
|
305
|
+
// In real application, save to database
|
|
306
|
+
localStorage.setItem('command-state', JSON.stringify(serialized));
|
|
307
|
+
return serialized.aseid;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Simulate loading command state from database/storage
|
|
311
|
+
async function loadCommandState(commandId: string) {
|
|
312
|
+
// In real application, load from database
|
|
313
|
+
const serialized = JSON.parse(localStorage.getItem('command-state') || '{}');
|
|
314
|
+
return new A_Command(serialized);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Usage
|
|
318
|
+
const command = new A_Command({ task: 'long-running-operation' });
|
|
319
|
+
A_Context.root.register(command);
|
|
320
|
+
|
|
321
|
+
await command.execute();
|
|
322
|
+
const commandId = await saveCommandState(command);
|
|
323
|
+
|
|
324
|
+
// Later, in different session...
|
|
325
|
+
const restoredCommand = await loadCommandState(commandId);
|
|
326
|
+
console.log('Restored command status:', restoredCommand.status);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Error Handling
|
|
330
|
+
|
|
331
|
+
### Capturing and Managing Errors
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import { A_Error } from '@adaas/a-concept';
|
|
335
|
+
|
|
336
|
+
class ErrorHandlingCommand extends A_Command<{}, {}> {}
|
|
337
|
+
|
|
338
|
+
class ErrorHandler extends A_Component {
|
|
339
|
+
|
|
340
|
+
@A_Feature.Extend({ scope: [ErrorHandlingCommand] })
|
|
341
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
342
|
+
@A_Inject(A_Memory) memory: A_Memory<{}>
|
|
343
|
+
) {
|
|
344
|
+
try {
|
|
345
|
+
// Simulate some operations that might fail
|
|
346
|
+
throw new Error('Simulated error');
|
|
347
|
+
} catch (error) {
|
|
348
|
+
// Add error to memory
|
|
349
|
+
await memory.error(new A_Error({
|
|
350
|
+
title: 'Operation Failed',
|
|
351
|
+
message: error.message,
|
|
352
|
+
code: 'OP_FAILED'
|
|
353
|
+
}));
|
|
354
|
+
|
|
355
|
+
// Throw error to trigger failure state
|
|
356
|
+
throw error;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
A_Context.reset();
|
|
362
|
+
A_Context.root.register(ErrorHandler);
|
|
363
|
+
|
|
364
|
+
const command = new ErrorHandlingCommand({});
|
|
365
|
+
A_Context.root.register(command);
|
|
366
|
+
|
|
367
|
+
await command.execute();
|
|
368
|
+
|
|
369
|
+
console.log('Command failed:', command.isFailed);
|
|
370
|
+
console.log('Errors:', Array.from(command.errors?.values() || []));
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Error Serialization
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
// Errors are automatically included in serialization
|
|
377
|
+
const serialized = command.toJSON();
|
|
378
|
+
console.log('Serialized errors:', serialized.errors);
|
|
379
|
+
|
|
380
|
+
// Errors are restored during deserialization
|
|
381
|
+
const restoredCommand = new ErrorHandlingCommand(serialized);
|
|
382
|
+
console.log('Restored errors:', restoredCommand.errors);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## API Reference
|
|
386
|
+
|
|
387
|
+
### A_Command Class
|
|
388
|
+
|
|
389
|
+
#### Constructor
|
|
390
|
+
```typescript
|
|
391
|
+
constructor(params: InvokeType | A_TYPES__Command_Serialized<InvokeType, ResultType> | string)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
#### Properties
|
|
395
|
+
- `code: string` - Unique identifier for the command type
|
|
396
|
+
- `status: A_CONSTANTS__A_Command_Status` - Current execution status
|
|
397
|
+
- `params: InvokeType` - Command parameters
|
|
398
|
+
- `result: ResultType | undefined` - Execution result
|
|
399
|
+
- `errors: Set<A_Error> | undefined` - Execution errors
|
|
400
|
+
- `startedAt: Date | undefined` - Execution start time
|
|
401
|
+
- `endedAt: Date | undefined` - Execution end time
|
|
402
|
+
- `duration: number | undefined` - Execution duration in milliseconds
|
|
403
|
+
- `scope: A_Scope` - Execution scope for dependency injection
|
|
404
|
+
- `isFailed: boolean` - Whether command failed
|
|
405
|
+
- `isCompleted: boolean` - Whether command completed successfully
|
|
406
|
+
|
|
407
|
+
#### Methods
|
|
408
|
+
- `async execute(): Promise<any>` - Execute the complete command lifecycle
|
|
409
|
+
- `async init(): Promise<void>` - Initialize command
|
|
410
|
+
- `async compile(): Promise<void>` - Compile command
|
|
411
|
+
- `async complete(): Promise<void>` - Mark command as completed
|
|
412
|
+
- `async fail(): Promise<void>` - Mark command as failed
|
|
413
|
+
- `on(event, listener)` - Add event listener
|
|
414
|
+
- `off(event, listener)` - Remove event listener
|
|
415
|
+
- `emit(event)` - Emit event
|
|
416
|
+
- `toJSON()` - Serialize command state
|
|
417
|
+
- `fromJSON(serialized)` - Deserialize command state
|
|
418
|
+
|
|
419
|
+
### Command Status Constants
|
|
420
|
+
```typescript
|
|
421
|
+
enum A_CONSTANTS__A_Command_Status {
|
|
422
|
+
CREATED = 'CREATED',
|
|
423
|
+
INITIALIZATION = 'INITIALIZATION',
|
|
424
|
+
INITIALIZED = 'INITIALIZED',
|
|
425
|
+
COMPILATION = 'COMPILATION',
|
|
426
|
+
COMPILED = 'COMPILED',
|
|
427
|
+
IN_PROGRESS = 'IN_PROGRESS',
|
|
428
|
+
COMPLETED = 'COMPLETED',
|
|
429
|
+
FAILED = 'FAILED'
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Lifecycle Features for Components
|
|
434
|
+
```typescript
|
|
435
|
+
enum A_CONSTANTS_A_Command_Features {
|
|
436
|
+
INIT = 'init',
|
|
437
|
+
COMPLIED = 'complied',
|
|
438
|
+
EXECUTE = 'execute',
|
|
439
|
+
COMPLETE = 'complete',
|
|
440
|
+
FAIL = 'fail'
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
## Examples
|
|
445
|
+
|
|
446
|
+
### File Processing Command
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
interface FileProcessParams {
|
|
450
|
+
filePath: string;
|
|
451
|
+
operation: 'compress' | 'encrypt' | 'convert';
|
|
452
|
+
options: Record<string, any>;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
interface FileProcessResult {
|
|
456
|
+
outputPath: string;
|
|
457
|
+
originalSize: number;
|
|
458
|
+
processedSize: number;
|
|
459
|
+
processingTime: number;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
class FileProcessCommand extends A_Command<FileProcessParams, FileProcessResult> {}
|
|
463
|
+
|
|
464
|
+
class FileProcessor extends A_Component {
|
|
465
|
+
|
|
466
|
+
@A_Feature.Extend({ scope: [FileProcessCommand] })
|
|
467
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
468
|
+
@A_Inject(A_Memory) memory: A_Memory<FileProcessResult>
|
|
469
|
+
) {
|
|
470
|
+
const command = A_Context.scope(this).resolve(FileProcessCommand);
|
|
471
|
+
const { filePath, operation, options } = command.params;
|
|
472
|
+
|
|
473
|
+
const startTime = Date.now();
|
|
474
|
+
|
|
475
|
+
// Simulate file processing
|
|
476
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
477
|
+
|
|
478
|
+
const endTime = Date.now();
|
|
479
|
+
|
|
480
|
+
await memory.set('outputPath', `processed_${filePath}`);
|
|
481
|
+
await memory.set('originalSize', 1024);
|
|
482
|
+
await memory.set('processedSize', 512);
|
|
483
|
+
await memory.set('processingTime', endTime - startTime);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Usage
|
|
488
|
+
A_Context.reset();
|
|
489
|
+
A_Context.root.register(FileProcessor);
|
|
490
|
+
|
|
491
|
+
const command = new FileProcessCommand({
|
|
492
|
+
filePath: '/path/to/file.txt',
|
|
493
|
+
operation: 'compress',
|
|
494
|
+
options: { quality: 0.8 }
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
A_Context.root.register(command);
|
|
498
|
+
await command.execute();
|
|
499
|
+
|
|
500
|
+
console.log('File processed:', command.result);
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Batch Processing with Progress Tracking
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
type BatchEvents = 'item-processed' | 'progress-update' | 'batch-complete';
|
|
507
|
+
|
|
508
|
+
interface BatchProcessParams {
|
|
509
|
+
items: Array<{ id: string; data: any }>;
|
|
510
|
+
batchSize: number;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
interface BatchProcessResult {
|
|
514
|
+
processedCount: number;
|
|
515
|
+
failedCount: number;
|
|
516
|
+
totalTime: number;
|
|
517
|
+
results: Array<{ id: string; success: boolean; result?: any; error?: string }>;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
class BatchProcessCommand extends A_Command<BatchProcessParams, BatchProcessResult, BatchEvents> {}
|
|
521
|
+
|
|
522
|
+
class BatchProcessor extends A_Component {
|
|
523
|
+
|
|
524
|
+
@A_Feature.Extend({ scope: [BatchProcessCommand] })
|
|
525
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
526
|
+
@A_Inject(A_Memory) memory: A_Memory<BatchProcessResult>
|
|
527
|
+
) {
|
|
528
|
+
const command = A_Context.scope(this).resolve(BatchProcessCommand);
|
|
529
|
+
const { items, batchSize } = command.params;
|
|
530
|
+
|
|
531
|
+
const results: Array<{ id: string; success: boolean; result?: any; error?: string }> = [];
|
|
532
|
+
let processedCount = 0;
|
|
533
|
+
let failedCount = 0;
|
|
534
|
+
|
|
535
|
+
// Process items in batches
|
|
536
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
537
|
+
const batch = items.slice(i, i + batchSize);
|
|
538
|
+
|
|
539
|
+
for (const item of batch) {
|
|
540
|
+
try {
|
|
541
|
+
// Simulate processing
|
|
542
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
543
|
+
|
|
544
|
+
results.push({
|
|
545
|
+
id: item.id,
|
|
546
|
+
success: true,
|
|
547
|
+
result: `processed-${item.id}`
|
|
548
|
+
});
|
|
549
|
+
processedCount++;
|
|
550
|
+
|
|
551
|
+
command.emit('item-processed');
|
|
552
|
+
} catch (error) {
|
|
553
|
+
results.push({
|
|
554
|
+
id: item.id,
|
|
555
|
+
success: false,
|
|
556
|
+
error: error.message
|
|
557
|
+
});
|
|
558
|
+
failedCount++;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
command.emit('progress-update');
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
await memory.set('processedCount', processedCount);
|
|
566
|
+
await memory.set('failedCount', failedCount);
|
|
567
|
+
await memory.set('totalTime', command.duration || 0);
|
|
568
|
+
await memory.set('results', results);
|
|
569
|
+
|
|
570
|
+
command.emit('batch-complete');
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Usage with progress tracking
|
|
575
|
+
A_Context.reset();
|
|
576
|
+
A_Context.root.register(BatchProcessor);
|
|
577
|
+
|
|
578
|
+
const command = new BatchProcessCommand({
|
|
579
|
+
items: Array.from({ length: 10 }, (_, i) => ({ id: `item-${i}`, data: {} })),
|
|
580
|
+
batchSize: 3
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
// Track progress
|
|
584
|
+
command.on('item-processed', () => {
|
|
585
|
+
console.log('Item processed');
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
command.on('progress-update', () => {
|
|
589
|
+
console.log('Batch completed');
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
command.on('batch-complete', () => {
|
|
593
|
+
console.log('All batches completed');
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
A_Context.root.register(command);
|
|
597
|
+
await command.execute();
|
|
598
|
+
|
|
599
|
+
console.log('Batch results:', command.result);
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
## Integration with A-Memory
|
|
603
|
+
|
|
604
|
+
A-Command automatically integrates with A-Memory for result and error storage:
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
// Access memory during execution
|
|
608
|
+
class MemoryIntegrationCommand extends A_Command<{}, { step1: string; step2: number }> {}
|
|
609
|
+
|
|
610
|
+
class MemoryUser extends A_Component {
|
|
611
|
+
|
|
612
|
+
@A_Feature.Extend({ scope: [MemoryIntegrationCommand] })
|
|
613
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
614
|
+
@A_Inject(A_Memory) memory: A_Memory<{ step1: string; step2: number }>
|
|
615
|
+
) {
|
|
616
|
+
// Store intermediate results
|
|
617
|
+
await memory.set('step1', 'completed');
|
|
618
|
+
await memory.set('step2', 42);
|
|
619
|
+
|
|
620
|
+
// Access stored values
|
|
621
|
+
const step1Result = memory.get('step1');
|
|
622
|
+
console.log('Step 1 result:', step1Result);
|
|
623
|
+
|
|
624
|
+
// Verify prerequisites
|
|
625
|
+
const hasRequiredData = await memory.verifyPrerequisites(['step1', 'step2']);
|
|
626
|
+
console.log('Has required data:', hasRequiredData);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## Contributing
|
|
634
|
+
|
|
635
|
+
When extending A-Command functionality, please ensure:
|
|
636
|
+
|
|
637
|
+
1. All new features include comprehensive tests
|
|
638
|
+
2. TypeScript types are properly defined and exported
|
|
639
|
+
3. Documentation is updated for new APIs
|
|
640
|
+
4. Examples are provided for complex features
|
|
641
|
+
5. Backward compatibility is maintained
|
|
642
|
+
|
|
643
|
+
## License
|
|
644
|
+
|
|
645
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
@@ -56,6 +56,21 @@ export class A_Memory<
|
|
|
56
56
|
this._errors.add(error);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Retrieves a value from the context memory
|
|
61
|
+
*
|
|
62
|
+
* @param key
|
|
63
|
+
* @returns
|
|
64
|
+
*/
|
|
65
|
+
get<K extends keyof _MemoryType>(
|
|
66
|
+
/**
|
|
67
|
+
* Key to retrieve the value for
|
|
68
|
+
*/
|
|
69
|
+
key: K
|
|
70
|
+
): _MemoryType[K] | undefined {
|
|
71
|
+
return this._memory.get(key);
|
|
72
|
+
}
|
|
73
|
+
|
|
59
74
|
/**
|
|
60
75
|
* Saves a value in the context memory
|
|
61
76
|
*
|