@miller-tech/uap 2.36.4 → 2.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/model-profiles/qwen38.json +3 -3
- package/config/model-registry.json +96 -6
- package/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +57 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/deliver.d.ts +46 -0
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +155 -36
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/models.d.ts +11 -1
- package/dist/cli/models.d.ts.map +1 -1
- package/dist/cli/models.js +164 -3
- package/dist/cli/models.js.map +1 -1
- package/dist/cli/workflow.d.ts +36 -0
- package/dist/cli/workflow.d.ts.map +1 -0
- package/dist/cli/workflow.js +246 -0
- package/dist/cli/workflow.js.map +1 -0
- package/dist/delivery/run-state.d.ts +1 -1
- package/dist/delivery/run-state.d.ts.map +1 -1
- package/dist/delivery/run-state.js +1 -1
- package/dist/delivery/run-state.js.map +1 -1
- package/dist/delivery/team-solve-deliver.d.ts +83 -0
- package/dist/delivery/team-solve-deliver.d.ts.map +1 -0
- package/dist/delivery/team-solve-deliver.js +191 -0
- package/dist/delivery/team-solve-deliver.js.map +1 -0
- package/dist/inference/model-files.d.ts +111 -0
- package/dist/inference/model-files.d.ts.map +1 -0
- package/dist/inference/model-files.js +172 -0
- package/dist/inference/model-files.js.map +1 -0
- package/dist/placement/registry.d.ts +650 -0
- package/dist/placement/registry.d.ts.map +1 -1
- package/dist/placement/registry.js +21 -0
- package/dist/placement/registry.js.map +1 -1
- package/dist/workflow/loader.d.ts +34 -0
- package/dist/workflow/loader.d.ts.map +1 -0
- package/dist/workflow/loader.js +232 -0
- package/dist/workflow/loader.js.map +1 -0
- package/dist/workflow/runner.d.ts +90 -0
- package/dist/workflow/runner.d.ts.map +1 -0
- package/dist/workflow/runner.js +416 -0
- package/dist/workflow/runner.js.map +1 -0
- package/dist/workflow/types.d.ts +400 -0
- package/dist/workflow/types.d.ts.map +1 -0
- package/dist/workflow/types.js +147 -0
- package/dist/workflow/types.js.map +1 -0
- package/docs/INDEX.md +1 -0
- package/docs/architecture/adr/0013-declarative-workflow-layer.md +99 -0
- package/docs/architecture/adr/0014-loop-steps-and-team-solve-deliver.md +142 -0
- package/docs/benchmarks/LCB_DROID_SMOKE.md +111 -0
- package/docs/guides/DELIVER.md +3 -1
- package/docs/guides/WORKFLOWS.md +179 -0
- package/docs/plans/model-performance-proof-options.md +39 -0
- package/docs/reference/CLI.md +33 -0
- package/docs/reference/CONFIGURATION.md +1 -0
- package/docs/reference/FEATURES.md +18 -0
- package/examples/auto-coordinator-example.js +127 -0
- package/examples/demo-order-solid.ts +19 -0
- package/examples/order-processing-strategy-pattern.ts +186 -0
- package/examples/order-processor-refactored.ts +473 -0
- package/examples/order-solid-refactor.ts +830 -0
- package/examples/refactored-order-processing.ts +106 -0
- package/examples/run-order-processing.ts +48 -0
- package/examples/solid-order-processing.ts +324 -0
- package/examples/strategy-pattern-example.ts +100 -0
- package/examples/workflows/team-solve/README.md +85 -0
- package/examples/workflows/team-solve/check-samples.sh +50 -0
- package/examples/workflows/team-solve/sample/task.md +22 -0
- package/examples/workflows/team-solve/sample/tests/1.in +2 -0
- package/examples/workflows/team-solve/sample/tests/1.out +1 -0
- package/examples/workflows/team-solve/sample/tests/2.in +2 -0
- package/examples/workflows/team-solve/sample/tests/2.out +1 -0
- package/examples/workflows/team-solve/sample/tests/3.in +2 -0
- package/examples/workflows/team-solve/sample/tests/3.out +1 -0
- package/examples/workflows/team-solve/sample/tests/4.in +2 -0
- package/examples/workflows/team-solve/sample/tests/4.out +1 -0
- package/examples/workflows/team-solve/sample/tests/5.in +1 -0
- package/examples/workflows/team-solve/sample/tests/5.out +1 -0
- package/examples/workflows/team-solve/steps/ideate-a.md +26 -0
- package/examples/workflows/team-solve/steps/ideate-b.md +28 -0
- package/examples/workflows/team-solve/steps/plan.md +20 -0
- package/examples/workflows/team-solve/steps/repair.md +25 -0
- package/examples/workflows/team-solve/steps/review.md +29 -0
- package/examples/workflows/team-solve/steps/solve.md +26 -0
- package/examples/workflows/team-solve/workflow.yaml +78 -0
- package/examples/workflows/team-solve-deliver/README.md +84 -0
- package/examples/workflows/team-solve-deliver/steps/ideate-a.md +25 -0
- package/examples/workflows/team-solve-deliver/steps/ideate-b.md +28 -0
- package/examples/workflows/team-solve-deliver/steps/plan.md +25 -0
- package/examples/workflows/team-solve-deliver/steps/repair.md +20 -0
- package/examples/workflows/team-solve-deliver/steps/review.md +31 -0
- package/examples/workflows/team-solve-deliver/steps/solve.md +28 -0
- package/examples/workflows/team-solve-deliver/steps/verify.md +9 -0
- package/examples/workflows/team-solve-deliver/workflow.yaml +74 -0
- package/package.json +2 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-311.pyc +0 -0
- package/src/policies/enforcers/__pycache__/expert_review_required.cpython-311.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-311.pyc +0 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-311.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-311.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +163 -18
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Order Processing System - SOLID Principles Refactoring
|
|
3
|
+
*
|
|
4
|
+
* This module demonstrates a refactored order processing system using SOLID principles
|
|
5
|
+
* and the Strategy Design Pattern.
|
|
6
|
+
*
|
|
7
|
+
* SOLID Principles Implemented:
|
|
8
|
+
* - Single Responsibility: Each class has one clear purpose
|
|
9
|
+
* - Open/Closed: New order types can be added without modifying existing code
|
|
10
|
+
* - Liskov Substitution: All strategies can be used interchangeably
|
|
11
|
+
* - Interface Segregation: Focused interfaces for specific needs
|
|
12
|
+
* - Dependency Inversion: Depends on abstractions (interfaces) not concretions
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Order type enumeration for type safety
|
|
17
|
+
*/
|
|
18
|
+
export enum OrderType {
|
|
19
|
+
DIGITAL = 'digital',
|
|
20
|
+
PHYSICAL = 'physical',
|
|
21
|
+
SUBSCRIPTION = 'subscription',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Order status enumeration for tracking order lifecycle
|
|
26
|
+
*/
|
|
27
|
+
export enum OrderStatus {
|
|
28
|
+
PENDING = 'pending',
|
|
29
|
+
DELIVERED = 'delivered',
|
|
30
|
+
SHIPPED = 'shipped',
|
|
31
|
+
ACTIVE = 'active',
|
|
32
|
+
FAILED = 'failed',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Order interface - defines the contract for order data
|
|
37
|
+
*/
|
|
38
|
+
export interface Order {
|
|
39
|
+
id: string;
|
|
40
|
+
type: OrderType;
|
|
41
|
+
status: OrderStatus;
|
|
42
|
+
customerEmail: string;
|
|
43
|
+
items: OrderItem[];
|
|
44
|
+
createdAt: Date;
|
|
45
|
+
updatedAt: Date;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* OrderItem interface for items within an order
|
|
50
|
+
*/
|
|
51
|
+
export interface OrderItem {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
quantity: number;
|
|
55
|
+
price: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Result interface for order processing operations
|
|
60
|
+
*/
|
|
61
|
+
export interface ProcessingResult {
|
|
62
|
+
success: boolean;
|
|
63
|
+
order: Order;
|
|
64
|
+
message: string;
|
|
65
|
+
timestamp: Date;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* OrderProcessor interface - Strategy Pattern
|
|
70
|
+
*
|
|
71
|
+
* This interface defines the contract for order processing strategies.
|
|
72
|
+
* Each concrete implementation handles a specific order type.
|
|
73
|
+
*/
|
|
74
|
+
export interface OrderProcessor {
|
|
75
|
+
/**
|
|
76
|
+
* Process the order according to its type
|
|
77
|
+
* @param order - The order to process
|
|
78
|
+
* @returns ProcessingResult with updated order and processing details
|
|
79
|
+
* @throws AppError if processing fails
|
|
80
|
+
*/
|
|
81
|
+
process(order: Order): Promise<ProcessingResult>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if this processor can handle the given order type
|
|
85
|
+
* @param type - The order type to check
|
|
86
|
+
* @returns true if this processor handles the type
|
|
87
|
+
*/
|
|
88
|
+
canHandle(type: OrderType): boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Custom error class for application-specific errors
|
|
93
|
+
*/
|
|
94
|
+
export class AppError extends Error {
|
|
95
|
+
constructor(
|
|
96
|
+
message: string,
|
|
97
|
+
public readonly code: string,
|
|
98
|
+
public readonly statusCode: number = 500
|
|
99
|
+
) {
|
|
100
|
+
super(message);
|
|
101
|
+
this.name = 'AppError';
|
|
102
|
+
Error.captureStackTrace(this, this.constructor);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* DigitalOrderProcessor - handles digital product orders
|
|
108
|
+
*
|
|
109
|
+
* Single Responsibility: Send download links and mark as delivered
|
|
110
|
+
*/
|
|
111
|
+
export class DigitalOrderProcessor implements OrderProcessor {
|
|
112
|
+
canHandle(type: OrderType): boolean {
|
|
113
|
+
return type === OrderType.DIGITAL;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async process(order: Order): Promise<ProcessingResult> {
|
|
117
|
+
// Validate input
|
|
118
|
+
if (!order.customerEmail) {
|
|
119
|
+
throw new AppError(
|
|
120
|
+
'Customer email is required for digital orders',
|
|
121
|
+
'MISSING_EMAIL',
|
|
122
|
+
400
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// Send email with download link
|
|
128
|
+
await this.sendDownloadLink(order.customerEmail, order.id);
|
|
129
|
+
|
|
130
|
+
const processedOrder: Order = {
|
|
131
|
+
...order,
|
|
132
|
+
status: OrderStatus.DELIVERED,
|
|
133
|
+
updatedAt: new Date(),
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
console.log(`Order processed: ${processedOrder.id}`);
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
success: true,
|
|
140
|
+
order: processedOrder,
|
|
141
|
+
message: 'Digital order processed successfully',
|
|
142
|
+
timestamp: new Date(),
|
|
143
|
+
};
|
|
144
|
+
} catch (error) {
|
|
145
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
order,
|
|
150
|
+
message: `Failed to process digital order: ${errorMessage}`,
|
|
151
|
+
timestamp: new Date(),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Sends download link email to customer
|
|
158
|
+
* @private
|
|
159
|
+
*/
|
|
160
|
+
private async sendDownloadLink(email: string, orderId: string): Promise<void> {
|
|
161
|
+
console.log(`Sending email with download link for order ${orderId}`);
|
|
162
|
+
// In production: await emailService.sendDownloadLink(email, orderId);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* PhysicalOrderProcessor - handles physical product orders
|
|
168
|
+
*
|
|
169
|
+
* Single Responsibility: Create shipping labels and mark as shipped
|
|
170
|
+
*/
|
|
171
|
+
export class PhysicalOrderProcessor implements OrderProcessor {
|
|
172
|
+
canHandle(type: OrderType): boolean {
|
|
173
|
+
return type === OrderType.PHYSICAL;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async process(order: Order): Promise<ProcessingResult> {
|
|
177
|
+
// Validate input
|
|
178
|
+
if (!order.items || order.items.length === 0) {
|
|
179
|
+
throw new AppError(
|
|
180
|
+
'Physical order must contain at least one item',
|
|
181
|
+
'EMPTY_ORDER',
|
|
182
|
+
400
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
// Create shipping label
|
|
188
|
+
await this.createShippingLabel(order);
|
|
189
|
+
|
|
190
|
+
const processedOrder: Order = {
|
|
191
|
+
...order,
|
|
192
|
+
status: OrderStatus.SHIPPED,
|
|
193
|
+
updatedAt: new Date(),
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
console.log(`Order processed: ${processedOrder.id}`);
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
success: true,
|
|
200
|
+
order: processedOrder,
|
|
201
|
+
message: 'Physical order processed successfully',
|
|
202
|
+
timestamp: new Date(),
|
|
203
|
+
};
|
|
204
|
+
} catch (error) {
|
|
205
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
206
|
+
|
|
207
|
+
const failedOrder: Order = {
|
|
208
|
+
...order,
|
|
209
|
+
status: OrderStatus.FAILED,
|
|
210
|
+
updatedAt: new Date(),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
success: false,
|
|
215
|
+
order: failedOrder,
|
|
216
|
+
message: `Failed to process physical order: ${errorMessage}`,
|
|
217
|
+
timestamp: new Date(),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Creates shipping label for the order
|
|
224
|
+
* @private
|
|
225
|
+
*/
|
|
226
|
+
private async createShippingLabel(order: Order): Promise<void> {
|
|
227
|
+
console.log(`Creating shipping label for order ${order.id}`);
|
|
228
|
+
// In production: await shippingService.createLabel(order);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* SubscriptionOrderProcessor - handles subscription orders
|
|
234
|
+
*
|
|
235
|
+
* Single Responsibility: Activate subscriptions and manage recurring billing
|
|
236
|
+
*/
|
|
237
|
+
export class SubscriptionOrderProcessor implements OrderProcessor {
|
|
238
|
+
canHandle(type: OrderType): boolean {
|
|
239
|
+
return type === OrderType.SUBSCRIPTION;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async process(order: Order): Promise<ProcessingResult> {
|
|
243
|
+
// Validate input
|
|
244
|
+
if (!order.customerEmail) {
|
|
245
|
+
throw new AppError(
|
|
246
|
+
'Customer email is required for subscriptions',
|
|
247
|
+
'MISSING_EMAIL',
|
|
248
|
+
400
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
// Activate subscription
|
|
254
|
+
await this.activateSubscription(order);
|
|
255
|
+
|
|
256
|
+
const processedOrder: Order = {
|
|
257
|
+
...order,
|
|
258
|
+
status: OrderStatus.ACTIVE,
|
|
259
|
+
updatedAt: new Date(),
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
console.log(`Order processed: ${processedOrder.id}`);
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
success: true,
|
|
266
|
+
order: processedOrder,
|
|
267
|
+
message: 'Subscription order processed successfully',
|
|
268
|
+
timestamp: new Date(),
|
|
269
|
+
};
|
|
270
|
+
} catch (error) {
|
|
271
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
272
|
+
|
|
273
|
+
const failedOrder: Order = {
|
|
274
|
+
...order,
|
|
275
|
+
status: OrderStatus.FAILED,
|
|
276
|
+
updatedAt: new Date(),
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
success: false,
|
|
281
|
+
order: failedOrder,
|
|
282
|
+
message: `Failed to process subscription order: ${errorMessage}`,
|
|
283
|
+
timestamp: new Date(),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Activates subscription service
|
|
290
|
+
* @private
|
|
291
|
+
*/
|
|
292
|
+
private async activateSubscription(order: Order): Promise<void> {
|
|
293
|
+
console.log(`Activating subscription for order ${order.id}`);
|
|
294
|
+
// In production: await subscriptionService.activate(order);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* OrderProcessorFactory - Creates appropriate processor for order type
|
|
300
|
+
*
|
|
301
|
+
* Single Responsibility: Select the correct strategy based on order type
|
|
302
|
+
* Follows Factory pattern for dependency inversion
|
|
303
|
+
*/
|
|
304
|
+
export class OrderProcessorFactory {
|
|
305
|
+
private processors: Map<OrderType, OrderProcessor> = new Map();
|
|
306
|
+
|
|
307
|
+
constructor() {
|
|
308
|
+
// Register available processors
|
|
309
|
+
this.registerProcessor(new DigitalOrderProcessor());
|
|
310
|
+
this.registerProcessor(new PhysicalOrderProcessor());
|
|
311
|
+
this.registerProcessor(new SubscriptionOrderProcessor());
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Register a processor for a specific order type
|
|
316
|
+
* @param processor - The processor to register
|
|
317
|
+
*/
|
|
318
|
+
private registerProcessor(processor: OrderProcessor): void {
|
|
319
|
+
for (const type of Object.values(OrderType)) {
|
|
320
|
+
if (processor.canHandle(type)) {
|
|
321
|
+
this.processors.set(type, processor);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get the appropriate processor for the given order type
|
|
328
|
+
* @param type - The order type
|
|
329
|
+
* @returns OrderProcessor instance
|
|
330
|
+
* @throws AppError if no processor found for the type
|
|
331
|
+
*/
|
|
332
|
+
getProcessor(type: OrderType): OrderProcessor {
|
|
333
|
+
const processor = this.processors.get(type);
|
|
334
|
+
|
|
335
|
+
if (!processor) {
|
|
336
|
+
throw new AppError(
|
|
337
|
+
`No processor found for order type: ${type}`,
|
|
338
|
+
'UNSUPPORTED_ORDER_TYPE',
|
|
339
|
+
400
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return processor;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Check if a processor exists for the given order type
|
|
348
|
+
* @param type - The order type to check
|
|
349
|
+
* @returns true if a processor is available
|
|
350
|
+
*/
|
|
351
|
+
hasProcessor(type: OrderType): boolean {
|
|
352
|
+
return this.processors.has(type);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* OrderProcessorContext - Orchestrates order processing
|
|
358
|
+
*
|
|
359
|
+
* Single Responsibility: Coordinate processing using the factory pattern
|
|
360
|
+
* Dependency Inversion: Depends on OrderProcessorFactory interface
|
|
361
|
+
*/
|
|
362
|
+
export class OrderProcessorContext {
|
|
363
|
+
private readonly factory: OrderProcessorFactory;
|
|
364
|
+
|
|
365
|
+
constructor(factory?: OrderProcessorFactory) {
|
|
366
|
+
this.factory = factory || new OrderProcessorFactory();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Process an order using the appropriate strategy
|
|
371
|
+
* @param order - The order to process
|
|
372
|
+
* @returns ProcessingResult with updated order and processing details
|
|
373
|
+
*/
|
|
374
|
+
async processOrder(order: Order): Promise<ProcessingResult> {
|
|
375
|
+
// Validate order structure
|
|
376
|
+
if (!order.id || !order.type) {
|
|
377
|
+
throw new AppError(
|
|
378
|
+
'Order must have valid id and type',
|
|
379
|
+
'INVALID_ORDER',
|
|
380
|
+
400
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Check if processor exists
|
|
385
|
+
if (!this.factory.hasProcessor(order.type)) {
|
|
386
|
+
throw new AppError(
|
|
387
|
+
`Unsupported order type: ${order.type}`,
|
|
388
|
+
'UNSUPPORTED_ORDER_TYPE',
|
|
389
|
+
400
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Get appropriate processor and execute
|
|
394
|
+
const processor = this.factory.getProcessor(order.type);
|
|
395
|
+
const result = await processor.process(order);
|
|
396
|
+
|
|
397
|
+
console.log(result.message);
|
|
398
|
+
return result;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Main entry point function for backwards compatibility
|
|
404
|
+
* Maintains the same signature as the original function
|
|
405
|
+
*/
|
|
406
|
+
export async function processOrder(order: Order): Promise<Order> {
|
|
407
|
+
const context = new OrderProcessorContext();
|
|
408
|
+
const result = await context.processOrder(order);
|
|
409
|
+
|
|
410
|
+
if (!result.success) {
|
|
411
|
+
throw new AppError(result.message, 'PROCESSING_FAILED', 500);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return result.order;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Example usage demonstrating the refactored code
|
|
419
|
+
*/
|
|
420
|
+
export async function demonstrateUsage(): Promise<void> {
|
|
421
|
+
const context = new OrderProcessorContext();
|
|
422
|
+
|
|
423
|
+
// Example 1: Digital order
|
|
424
|
+
const digitalOrder: Order = {
|
|
425
|
+
id: 'order-001',
|
|
426
|
+
type: OrderType.DIGITAL,
|
|
427
|
+
status: OrderStatus.PENDING,
|
|
428
|
+
customerEmail: 'customer@example.com',
|
|
429
|
+
items: [{ id: 'item-1', name: 'E-book', quantity: 1, price: 9.99 }],
|
|
430
|
+
createdAt: new Date(),
|
|
431
|
+
updatedAt: new Date(),
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
console.log('\n--- Processing Digital Order ---');
|
|
435
|
+
const digitalResult = await context.processOrder(digitalOrder);
|
|
436
|
+
console.log('Digital Order Result:', digitalResult);
|
|
437
|
+
|
|
438
|
+
// Example 2: Physical order
|
|
439
|
+
const physicalOrder: Order = {
|
|
440
|
+
id: 'order-002',
|
|
441
|
+
type: OrderType.PHYSICAL,
|
|
442
|
+
status: OrderStatus.PENDING,
|
|
443
|
+
customerEmail: 'customer@example.com',
|
|
444
|
+
items: [{ id: 'item-2', name: 'T-shirt', quantity: 2, price: 29.99 }],
|
|
445
|
+
createdAt: new Date(),
|
|
446
|
+
updatedAt: new Date(),
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
console.log('\n--- Processing Physical Order ---');
|
|
450
|
+
const physicalResult = await context.processOrder(physicalOrder);
|
|
451
|
+
console.log('Physical Order Result:', physicalResult);
|
|
452
|
+
|
|
453
|
+
// Example 3: Subscription order
|
|
454
|
+
const subscriptionOrder: Order = {
|
|
455
|
+
id: 'order-003',
|
|
456
|
+
type: OrderType.SUBSCRIPTION,
|
|
457
|
+
status: OrderStatus.PENDING,
|
|
458
|
+
customerEmail: 'customer@example.com',
|
|
459
|
+
items: [{ id: 'item-3', name: 'Premium Plan', quantity: 1, price: 19.99 }],
|
|
460
|
+
createdAt: new Date(),
|
|
461
|
+
updatedAt: new Date(),
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
console.log('\n--- Processing Subscription Order ---');
|
|
465
|
+
const subscriptionResult = await context.processOrder(subscriptionOrder);
|
|
466
|
+
console.log('Subscription Order Result:', subscriptionResult);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// If run directly, demonstrate usage
|
|
470
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
471
|
+
if (isMainModule) {
|
|
472
|
+
demonstrateUsage().catch(console.error);
|
|
473
|
+
}
|