universal-agent-memory 0.7.3 → 0.8.0
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 +121 -20
- package/dist/cli/memory.js +27 -0
- package/dist/cli/memory.js.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +2 -2
- package/dist/cli/update.js.map +1 -1
- package/dist/memory/adaptive-context.d.ts +100 -0
- package/dist/memory/adaptive-context.d.ts.map +1 -0
- package/dist/memory/adaptive-context.js +456 -0
- package/dist/memory/adaptive-context.js.map +1 -0
- package/dist/utils/calculate-average.d.ts +15 -0
- package/dist/utils/calculate-average.d.ts.map +1 -0
- package/dist/utils/calculate-average.js +21 -0
- package/dist/utils/calculate-average.js.map +1 -0
- package/dist/utils/config-manager.d.ts +30 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +41 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/fetch-with-retry.d.ts +5 -0
- package/dist/utils/fetch-with-retry.d.ts.map +1 -0
- package/dist/utils/fetch-with-retry.js +61 -0
- package/dist/utils/fetch-with-retry.js.map +1 -0
- package/dist/utils/order-processor-refactored.d.ts +126 -0
- package/dist/utils/order-processor-refactored.d.ts.map +1 -0
- package/dist/utils/order-processor-refactored.js +165 -0
- package/dist/utils/order-processor-refactored.js.map +1 -0
- package/dist/utils/order-processor-strategy.d.ts +72 -0
- package/dist/utils/order-processor-strategy.d.ts.map +1 -0
- package/dist/utils/order-processor-strategy.js +158 -0
- package/dist/utils/order-processor-strategy.js.map +1 -0
- package/dist/utils/order-processor.d.ts +242 -0
- package/dist/utils/order-processor.d.ts.map +1 -0
- package/dist/utils/order-processor.js +370 -0
- package/dist/utils/order-processor.js.map +1 -0
- package/dist/utils/rate-limiter-simple.d.ts +58 -0
- package/dist/utils/rate-limiter-simple.d.ts.map +1 -0
- package/dist/utils/rate-limiter-simple.js +100 -0
- package/dist/utils/rate-limiter-simple.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Order Processing System - SOLID Principles Implementation
|
|
3
|
+
*
|
|
4
|
+
* This module demonstrates a refactored order processing system using:
|
|
5
|
+
* - Single Responsibility Principle: Each strategy handles one order type
|
|
6
|
+
* - Open/Closed Principle: New order types can be added without modifying existing code
|
|
7
|
+
* - Liskov Substitution Principle: All strategies can be used interchangeably
|
|
8
|
+
* - Interface Segregation Principle: Focused interfaces for specific needs
|
|
9
|
+
* - Dependency Inversion Principle: Depends on abstractions (interfaces) not concretions
|
|
10
|
+
*/
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
/**
|
|
13
|
+
* Order type enum
|
|
14
|
+
*/
|
|
15
|
+
export declare enum OrderType {
|
|
16
|
+
DIGITAL = "digital",
|
|
17
|
+
PHYSICAL = "physical",
|
|
18
|
+
SUBSCRIPTION = "subscription"
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Order status enum
|
|
22
|
+
*/
|
|
23
|
+
export declare enum OrderStatus {
|
|
24
|
+
PENDING = "pending",
|
|
25
|
+
DELIVERED = "delivered",
|
|
26
|
+
SHIPPED = "shipped",
|
|
27
|
+
ACTIVE = "active"
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Order interface
|
|
31
|
+
*/
|
|
32
|
+
export interface Order {
|
|
33
|
+
id: string;
|
|
34
|
+
type: OrderType;
|
|
35
|
+
status: OrderStatus;
|
|
36
|
+
customerId: string;
|
|
37
|
+
items: Array<{
|
|
38
|
+
productId: string;
|
|
39
|
+
quantity: number;
|
|
40
|
+
price: number;
|
|
41
|
+
}>;
|
|
42
|
+
createdAt: Date;
|
|
43
|
+
updatedAt: Date;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Order processing result interface
|
|
47
|
+
*/
|
|
48
|
+
export interface ProcessingResult {
|
|
49
|
+
success: boolean;
|
|
50
|
+
order: Order;
|
|
51
|
+
message: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Order validation schema using Zod
|
|
55
|
+
*/
|
|
56
|
+
export declare const OrderSchema: z.ZodObject<{
|
|
57
|
+
id: z.ZodString;
|
|
58
|
+
type: z.ZodNativeEnum<typeof OrderType>;
|
|
59
|
+
status: z.ZodDefault<z.ZodNativeEnum<typeof OrderStatus>>;
|
|
60
|
+
customerId: z.ZodString;
|
|
61
|
+
items: z.ZodArray<z.ZodObject<{
|
|
62
|
+
productId: z.ZodString;
|
|
63
|
+
quantity: z.ZodNumber;
|
|
64
|
+
price: z.ZodNumber;
|
|
65
|
+
}, "strip", z.ZodTypeAny, {
|
|
66
|
+
price: number;
|
|
67
|
+
productId: string;
|
|
68
|
+
quantity: number;
|
|
69
|
+
}, {
|
|
70
|
+
price: number;
|
|
71
|
+
productId: string;
|
|
72
|
+
quantity: number;
|
|
73
|
+
}>, "many">;
|
|
74
|
+
createdAt: z.ZodDate;
|
|
75
|
+
updatedAt: z.ZodDate;
|
|
76
|
+
}, "strip", z.ZodTypeAny, {
|
|
77
|
+
type: OrderType;
|
|
78
|
+
status: OrderStatus;
|
|
79
|
+
id: string;
|
|
80
|
+
createdAt: Date;
|
|
81
|
+
customerId: string;
|
|
82
|
+
items: {
|
|
83
|
+
price: number;
|
|
84
|
+
productId: string;
|
|
85
|
+
quantity: number;
|
|
86
|
+
}[];
|
|
87
|
+
updatedAt: Date;
|
|
88
|
+
}, {
|
|
89
|
+
type: OrderType;
|
|
90
|
+
id: string;
|
|
91
|
+
createdAt: Date;
|
|
92
|
+
customerId: string;
|
|
93
|
+
items: {
|
|
94
|
+
price: number;
|
|
95
|
+
productId: string;
|
|
96
|
+
quantity: number;
|
|
97
|
+
}[];
|
|
98
|
+
updatedAt: Date;
|
|
99
|
+
status?: OrderStatus | undefined;
|
|
100
|
+
}>;
|
|
101
|
+
/**
|
|
102
|
+
* OrderProcessor strategy interface
|
|
103
|
+
* All order processors must implement this interface
|
|
104
|
+
*/
|
|
105
|
+
export interface OrderProcessor {
|
|
106
|
+
/**
|
|
107
|
+
* Process an order according to its type
|
|
108
|
+
* @param order - The order to process
|
|
109
|
+
* @returns Processing result with updated order status
|
|
110
|
+
* @throws {Error} If processing fails
|
|
111
|
+
*/
|
|
112
|
+
process(order: Order): Promise<ProcessingResult>;
|
|
113
|
+
/**
|
|
114
|
+
* Validate that the order can be processed
|
|
115
|
+
* @param order - The order to validate
|
|
116
|
+
* @returns true if valid, false otherwise
|
|
117
|
+
*/
|
|
118
|
+
validate(order: Order): boolean;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Digital order processor strategy
|
|
122
|
+
* Handles delivery of digital products via email
|
|
123
|
+
*/
|
|
124
|
+
export declare class DigitalOrderProcessor implements OrderProcessor {
|
|
125
|
+
/**
|
|
126
|
+
* Process a digital order
|
|
127
|
+
* @param order - The digital order to process
|
|
128
|
+
* @returns Processing result with delivered status
|
|
129
|
+
* @throws {Error} If email delivery fails
|
|
130
|
+
*/
|
|
131
|
+
process(order: Order): Promise<ProcessingResult>;
|
|
132
|
+
/**
|
|
133
|
+
* Validate digital order requirements
|
|
134
|
+
* @param order - The order to validate
|
|
135
|
+
* @returns true if valid for digital processing
|
|
136
|
+
*/
|
|
137
|
+
validate(order: Order): boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Send download link email to customer
|
|
140
|
+
* @param order - The order containing customer information
|
|
141
|
+
* @throws {Error} If email cannot be sent
|
|
142
|
+
*/
|
|
143
|
+
private sendDownloadLinkEmail;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Physical order processor strategy
|
|
147
|
+
* Handles shipping of physical products
|
|
148
|
+
*/
|
|
149
|
+
export declare class PhysicalOrderProcessor implements OrderProcessor {
|
|
150
|
+
/**
|
|
151
|
+
* Process a physical order
|
|
152
|
+
* @param order - The physical order to process
|
|
153
|
+
* @returns Processing result with shipped status
|
|
154
|
+
* @throws {Error} If shipping label creation fails
|
|
155
|
+
*/
|
|
156
|
+
process(order: Order): Promise<ProcessingResult>;
|
|
157
|
+
/**
|
|
158
|
+
* Validate physical order requirements
|
|
159
|
+
* @param order - The order to validate
|
|
160
|
+
* @returns true if valid for physical processing
|
|
161
|
+
*/
|
|
162
|
+
validate(order: Order): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* Create shipping label for the order
|
|
165
|
+
* @param order - The order to create label for
|
|
166
|
+
* @throws {Error} If shipping label cannot be created
|
|
167
|
+
*/
|
|
168
|
+
private createShippingLabel;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Subscription order processor strategy
|
|
172
|
+
* Handles activation of subscription services
|
|
173
|
+
*/
|
|
174
|
+
export declare class SubscriptionOrderProcessor implements OrderProcessor {
|
|
175
|
+
/**
|
|
176
|
+
* Process a subscription order
|
|
177
|
+
* @param order - The subscription order to process
|
|
178
|
+
* @returns Processing result with active status
|
|
179
|
+
* @throws {Error} If subscription activation fails
|
|
180
|
+
*/
|
|
181
|
+
process(order: Order): Promise<ProcessingResult>;
|
|
182
|
+
/**
|
|
183
|
+
* Validate subscription order requirements
|
|
184
|
+
* @param order - The order to validate
|
|
185
|
+
* @returns true if valid for subscription processing
|
|
186
|
+
*/
|
|
187
|
+
validate(order: Order): boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Activate subscription service
|
|
190
|
+
* @param order - The order containing subscription details
|
|
191
|
+
* @throws {Error} If subscription cannot be activated
|
|
192
|
+
*/
|
|
193
|
+
private activateSubscription;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* OrderProcessor factory
|
|
197
|
+
* Responsible for selecting the appropriate processor based on order type
|
|
198
|
+
* Follows Factory pattern for dependency injection
|
|
199
|
+
*/
|
|
200
|
+
export declare class OrderProcessorFactory {
|
|
201
|
+
private readonly processors;
|
|
202
|
+
constructor();
|
|
203
|
+
/**
|
|
204
|
+
* Get the appropriate processor for the given order type
|
|
205
|
+
* @param orderType - The type of order
|
|
206
|
+
* @returns The appropriate order processor
|
|
207
|
+
* @throws {Error} If no processor is found for the order type
|
|
208
|
+
*/
|
|
209
|
+
getProcessor(orderType: OrderType): OrderProcessor;
|
|
210
|
+
/**
|
|
211
|
+
* Register a new processor for a specific order type
|
|
212
|
+
* @param orderType - The order type to handle
|
|
213
|
+
* @param processor - The processor implementation
|
|
214
|
+
*/
|
|
215
|
+
registerProcessor(orderType: OrderType, processor: OrderProcessor): void;
|
|
216
|
+
/**
|
|
217
|
+
* Check if a processor is registered for the given order type
|
|
218
|
+
* @param orderType - The order type to check
|
|
219
|
+
* @returns true if a processor exists
|
|
220
|
+
*/
|
|
221
|
+
hasProcessor(orderType: OrderType): boolean;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* OrderProcessingService
|
|
225
|
+
* Main service that coordinates order processing using the appropriate strategy
|
|
226
|
+
*/
|
|
227
|
+
export declare class OrderProcessingService {
|
|
228
|
+
private readonly processorFactory;
|
|
229
|
+
constructor(processorFactory?: OrderProcessorFactory);
|
|
230
|
+
/**
|
|
231
|
+
* Process an order using the appropriate strategy
|
|
232
|
+
* @param orderInput - The order data to process (may be unvalidated)
|
|
233
|
+
* @returns Processing result with updated order
|
|
234
|
+
* @throws {Error} If validation fails or processing encounters an error
|
|
235
|
+
*/
|
|
236
|
+
processOrder(orderInput: unknown): Promise<ProcessingResult>;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Example usage demonstrating the refactored code
|
|
240
|
+
*/
|
|
241
|
+
export declare function exampleUsage(): Promise<void>;
|
|
242
|
+
//# sourceMappingURL=order-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order-processor.d.ts","sourceRoot":"","sources":["../../src/utils/order-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Order Processing System - SOLID Principles Implementation
|
|
3
|
+
*
|
|
4
|
+
* This module demonstrates a refactored order processing system using:
|
|
5
|
+
* - Single Responsibility Principle: Each strategy handles one order type
|
|
6
|
+
* - Open/Closed Principle: New order types can be added without modifying existing code
|
|
7
|
+
* - Liskov Substitution Principle: All strategies can be used interchangeably
|
|
8
|
+
* - Interface Segregation Principle: Focused interfaces for specific needs
|
|
9
|
+
* - Dependency Inversion Principle: Depends on abstractions (interfaces) not concretions
|
|
10
|
+
*/
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
/**
|
|
13
|
+
* Order type enum
|
|
14
|
+
*/
|
|
15
|
+
export var OrderType;
|
|
16
|
+
(function (OrderType) {
|
|
17
|
+
OrderType["DIGITAL"] = "digital";
|
|
18
|
+
OrderType["PHYSICAL"] = "physical";
|
|
19
|
+
OrderType["SUBSCRIPTION"] = "subscription";
|
|
20
|
+
})(OrderType || (OrderType = {}));
|
|
21
|
+
/**
|
|
22
|
+
* Order status enum
|
|
23
|
+
*/
|
|
24
|
+
export var OrderStatus;
|
|
25
|
+
(function (OrderStatus) {
|
|
26
|
+
OrderStatus["PENDING"] = "pending";
|
|
27
|
+
OrderStatus["DELIVERED"] = "delivered";
|
|
28
|
+
OrderStatus["SHIPPED"] = "shipped";
|
|
29
|
+
OrderStatus["ACTIVE"] = "active";
|
|
30
|
+
})(OrderStatus || (OrderStatus = {}));
|
|
31
|
+
/**
|
|
32
|
+
* Order validation schema using Zod
|
|
33
|
+
*/
|
|
34
|
+
export const OrderSchema = z.object({
|
|
35
|
+
id: z.string().min(1, 'Order ID is required'),
|
|
36
|
+
type: z.nativeEnum(OrderType),
|
|
37
|
+
status: z.nativeEnum(OrderStatus).default(OrderStatus.PENDING),
|
|
38
|
+
customerId: z.string().min(1, 'Customer ID is required'),
|
|
39
|
+
items: z.array(z.object({
|
|
40
|
+
productId: z.string().min(1, 'Product ID is required'),
|
|
41
|
+
quantity: z.number().int().positive('Quantity must be positive'),
|
|
42
|
+
price: z.number().positive('Price must be positive'),
|
|
43
|
+
})).min(1, 'At least one item is required'),
|
|
44
|
+
createdAt: z.date(),
|
|
45
|
+
updatedAt: z.date(),
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Digital order processor strategy
|
|
49
|
+
* Handles delivery of digital products via email
|
|
50
|
+
*/
|
|
51
|
+
export class DigitalOrderProcessor {
|
|
52
|
+
/**
|
|
53
|
+
* Process a digital order
|
|
54
|
+
* @param order - The digital order to process
|
|
55
|
+
* @returns Processing result with delivered status
|
|
56
|
+
* @throws {Error} If email delivery fails
|
|
57
|
+
*/
|
|
58
|
+
async process(order) {
|
|
59
|
+
try {
|
|
60
|
+
// Send email with download link
|
|
61
|
+
await this.sendDownloadLinkEmail(order);
|
|
62
|
+
const processedOrder = {
|
|
63
|
+
...order,
|
|
64
|
+
status: OrderStatus.DELIVERED,
|
|
65
|
+
updatedAt: new Date(),
|
|
66
|
+
};
|
|
67
|
+
console.log(`Digital order ${order.id} delivered successfully`);
|
|
68
|
+
return {
|
|
69
|
+
success: true,
|
|
70
|
+
order: processedOrder,
|
|
71
|
+
message: `Digital order ${order.id} has been delivered via email`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error(`Failed to process digital order ${order.id}:`, error);
|
|
76
|
+
throw new Error(`Failed to process digital order: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validate digital order requirements
|
|
81
|
+
* @param order - The order to validate
|
|
82
|
+
* @returns true if valid for digital processing
|
|
83
|
+
*/
|
|
84
|
+
validate(order) {
|
|
85
|
+
return order.type === OrderType.DIGITAL && order.status === OrderStatus.PENDING;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Send download link email to customer
|
|
89
|
+
* @param order - The order containing customer information
|
|
90
|
+
* @throws {Error} If email cannot be sent
|
|
91
|
+
*/
|
|
92
|
+
async sendDownloadLinkEmail(order) {
|
|
93
|
+
// Simulate email sending
|
|
94
|
+
console.log(`Sending email with download link for order ${order.id} to customer ${order.customerId}`);
|
|
95
|
+
// In production: await emailService.sendDownloadLink(order.customerId, order.items);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Physical order processor strategy
|
|
100
|
+
* Handles shipping of physical products
|
|
101
|
+
*/
|
|
102
|
+
export class PhysicalOrderProcessor {
|
|
103
|
+
/**
|
|
104
|
+
* Process a physical order
|
|
105
|
+
* @param order - The physical order to process
|
|
106
|
+
* @returns Processing result with shipped status
|
|
107
|
+
* @throws {Error} If shipping label creation fails
|
|
108
|
+
*/
|
|
109
|
+
async process(order) {
|
|
110
|
+
try {
|
|
111
|
+
// Create shipping label
|
|
112
|
+
await this.createShippingLabel(order);
|
|
113
|
+
const processedOrder = {
|
|
114
|
+
...order,
|
|
115
|
+
status: OrderStatus.SHIPPED,
|
|
116
|
+
updatedAt: new Date(),
|
|
117
|
+
};
|
|
118
|
+
console.log(`Physical order ${order.id} shipped successfully`);
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
order: processedOrder,
|
|
122
|
+
message: `Physical order ${order.id} has been shipped`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error(`Failed to process physical order ${order.id}:`, error);
|
|
127
|
+
throw new Error(`Failed to process physical order: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Validate physical order requirements
|
|
132
|
+
* @param order - The order to validate
|
|
133
|
+
* @returns true if valid for physical processing
|
|
134
|
+
*/
|
|
135
|
+
validate(order) {
|
|
136
|
+
return order.type === OrderType.PHYSICAL && order.status === OrderStatus.PENDING;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Create shipping label for the order
|
|
140
|
+
* @param order - The order to create label for
|
|
141
|
+
* @throws {Error} If shipping label cannot be created
|
|
142
|
+
*/
|
|
143
|
+
async createShippingLabel(_order) {
|
|
144
|
+
// Intentionally unused in this stub implementation
|
|
145
|
+
console.log('Creating shipping label');
|
|
146
|
+
// In production: await shippingService.createLabel(order);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Subscription order processor strategy
|
|
151
|
+
* Handles activation of subscription services
|
|
152
|
+
*/
|
|
153
|
+
export class SubscriptionOrderProcessor {
|
|
154
|
+
/**
|
|
155
|
+
* Process a subscription order
|
|
156
|
+
* @param order - The subscription order to process
|
|
157
|
+
* @returns Processing result with active status
|
|
158
|
+
* @throws {Error} If subscription activation fails
|
|
159
|
+
*/
|
|
160
|
+
async process(order) {
|
|
161
|
+
try {
|
|
162
|
+
// Activate subscription
|
|
163
|
+
await this.activateSubscription(order);
|
|
164
|
+
const processedOrder = {
|
|
165
|
+
...order,
|
|
166
|
+
status: OrderStatus.ACTIVE,
|
|
167
|
+
updatedAt: new Date(),
|
|
168
|
+
};
|
|
169
|
+
console.log(`Subscription order ${order.id} activated successfully`);
|
|
170
|
+
return {
|
|
171
|
+
success: true,
|
|
172
|
+
order: processedOrder,
|
|
173
|
+
message: `Subscription order ${order.id} has been activated`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
console.error(`Failed to process subscription order ${order.id}:`, error);
|
|
178
|
+
throw new Error(`Failed to process subscription order: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Validate subscription order requirements
|
|
183
|
+
* @param order - The order to validate
|
|
184
|
+
* @returns true if valid for subscription processing
|
|
185
|
+
*/
|
|
186
|
+
validate(order) {
|
|
187
|
+
return order.type === OrderType.SUBSCRIPTION && order.status === OrderStatus.PENDING;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Activate subscription service
|
|
191
|
+
* @param order - The order containing subscription details
|
|
192
|
+
* @throws {Error} If subscription cannot be activated
|
|
193
|
+
*/
|
|
194
|
+
async activateSubscription(_order) {
|
|
195
|
+
// Intentionally unused in this stub implementation
|
|
196
|
+
console.log('Activating subscription');
|
|
197
|
+
// In production: await subscriptionService.activate(order.customerId, order.items);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* OrderProcessor factory
|
|
202
|
+
* Responsible for selecting the appropriate processor based on order type
|
|
203
|
+
* Follows Factory pattern for dependency injection
|
|
204
|
+
*/
|
|
205
|
+
export class OrderProcessorFactory {
|
|
206
|
+
processors;
|
|
207
|
+
constructor() {
|
|
208
|
+
// Register all available processors
|
|
209
|
+
this.processors = newMap([
|
|
210
|
+
[OrderType.DIGITAL, new DigitalOrderProcessor()],
|
|
211
|
+
[OrderType.PHYSICAL, new PhysicalOrderProcessor()],
|
|
212
|
+
[OrderType.SUBSCRIPTION, new SubscriptionOrderProcessor()],
|
|
213
|
+
]);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get the appropriate processor for the given order type
|
|
217
|
+
* @param orderType - The type of order
|
|
218
|
+
* @returns The appropriate order processor
|
|
219
|
+
* @throws {Error} If no processor is found for the order type
|
|
220
|
+
*/
|
|
221
|
+
getProcessor(orderType) {
|
|
222
|
+
const processor = this.processors.get(orderType);
|
|
223
|
+
if (!processor) {
|
|
224
|
+
throw new Error(`No processor found for order type: ${orderType}`);
|
|
225
|
+
}
|
|
226
|
+
return processor;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Register a new processor for a specific order type
|
|
230
|
+
* @param orderType - The order type to handle
|
|
231
|
+
* @param processor - The processor implementation
|
|
232
|
+
*/
|
|
233
|
+
registerProcessor(orderType, processor) {
|
|
234
|
+
this.processors.set(orderType, processor);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Check if a processor is registered for the given order type
|
|
238
|
+
* @param orderType - The order type to check
|
|
239
|
+
* @returns true if a processor exists
|
|
240
|
+
*/
|
|
241
|
+
hasProcessor(orderType) {
|
|
242
|
+
return this.processors.has(orderType);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Helper function to create a typed Map
|
|
247
|
+
* @param entries - Initial entries for the Map
|
|
248
|
+
* @returns A new Map with the specified entries
|
|
249
|
+
*/
|
|
250
|
+
function newMap(entries) {
|
|
251
|
+
return new Map(entries);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* OrderProcessingService
|
|
255
|
+
* Main service that coordinates order processing using the appropriate strategy
|
|
256
|
+
*/
|
|
257
|
+
export class OrderProcessingService {
|
|
258
|
+
processorFactory;
|
|
259
|
+
constructor(processorFactory) {
|
|
260
|
+
this.processorFactory = processorFactory || new OrderProcessorFactory();
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Process an order using the appropriate strategy
|
|
264
|
+
* @param orderInput - The order data to process (may be unvalidated)
|
|
265
|
+
* @returns Processing result with updated order
|
|
266
|
+
* @throws {Error} If validation fails or processing encounters an error
|
|
267
|
+
*/
|
|
268
|
+
async processOrder(orderInput) {
|
|
269
|
+
try {
|
|
270
|
+
// Validate input using Zod schema
|
|
271
|
+
const order = OrderSchema.parse(orderInput);
|
|
272
|
+
console.log(`Processing order ${order.id} of type ${order.type}`);
|
|
273
|
+
// Get the appropriate processor
|
|
274
|
+
const processor = this.processorFactory.getProcessor(order.type);
|
|
275
|
+
// Validate that the order can be processed
|
|
276
|
+
if (!processor.validate(order)) {
|
|
277
|
+
throw new Error(`Order ${order.id} with status ${order.status} cannot be processed`);
|
|
278
|
+
}
|
|
279
|
+
// Process the order using the selected strategy
|
|
280
|
+
const result = await processor.process(order);
|
|
281
|
+
console.log(result.message);
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
if (error instanceof z.ZodError) {
|
|
286
|
+
console.error('Validation error:', error.errors);
|
|
287
|
+
throw new Error(`Order validation failed: ${error.errors.map(e => e.message).join(', ')}`);
|
|
288
|
+
}
|
|
289
|
+
console.error('Order processing error:', error);
|
|
290
|
+
throw error;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Example usage demonstrating the refactored code
|
|
296
|
+
*/
|
|
297
|
+
export async function exampleUsage() {
|
|
298
|
+
// Initialize the service
|
|
299
|
+
const orderService = new OrderProcessingService();
|
|
300
|
+
// Example 1: Digital order
|
|
301
|
+
const digitalOrder = {
|
|
302
|
+
id: 'ORD-001',
|
|
303
|
+
type: OrderType.DIGITAL,
|
|
304
|
+
status: OrderStatus.PENDING,
|
|
305
|
+
customerId: 'CUST-123',
|
|
306
|
+
items: [
|
|
307
|
+
{
|
|
308
|
+
productId: 'PROD-DIG-001',
|
|
309
|
+
quantity: 1,
|
|
310
|
+
price: 29.99,
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
createdAt: new Date(),
|
|
314
|
+
updatedAt: new Date(),
|
|
315
|
+
};
|
|
316
|
+
try {
|
|
317
|
+
const result1 = await orderService.processOrder(digitalOrder);
|
|
318
|
+
console.log('Result:', result1);
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
console.error('Error:', error);
|
|
322
|
+
}
|
|
323
|
+
// Example 2: Physical order
|
|
324
|
+
const physicalOrder = {
|
|
325
|
+
id: 'ORD-002',
|
|
326
|
+
type: OrderType.PHYSICAL,
|
|
327
|
+
status: OrderStatus.PENDING,
|
|
328
|
+
customerId: 'CUST-456',
|
|
329
|
+
items: [
|
|
330
|
+
{
|
|
331
|
+
productId: 'PROD-PHY-001',
|
|
332
|
+
quantity: 2,
|
|
333
|
+
price: 49.99,
|
|
334
|
+
},
|
|
335
|
+
],
|
|
336
|
+
createdAt: new Date(),
|
|
337
|
+
updatedAt: new Date(),
|
|
338
|
+
};
|
|
339
|
+
try {
|
|
340
|
+
const result2 = await orderService.processOrder(physicalOrder);
|
|
341
|
+
console.log('Result:', result2);
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
console.error('Error:', error);
|
|
345
|
+
}
|
|
346
|
+
// Example 3: Subscription order
|
|
347
|
+
const subscriptionOrder = {
|
|
348
|
+
id: 'ORD-003',
|
|
349
|
+
type: OrderType.SUBSCRIPTION,
|
|
350
|
+
status: OrderStatus.PENDING,
|
|
351
|
+
customerId: 'CUST-789',
|
|
352
|
+
items: [
|
|
353
|
+
{
|
|
354
|
+
productId: 'PROD-SUB-001',
|
|
355
|
+
quantity: 1,
|
|
356
|
+
price: 19.99,
|
|
357
|
+
},
|
|
358
|
+
],
|
|
359
|
+
createdAt: new Date(),
|
|
360
|
+
updatedAt: new Date(),
|
|
361
|
+
};
|
|
362
|
+
try {
|
|
363
|
+
const result3 = await orderService.processOrder(subscriptionOrder);
|
|
364
|
+
console.log('Result:', result3);
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
console.error('Error:', error);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=order-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order-processor.js","sourceRoot":"","sources":["../../src/utils/order-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for the RateLimiter.
|
|
3
|
+
*/
|
|
4
|
+
export interface RateLimiterConfig {
|
|
5
|
+
/** Maximum number of requests allowed within the time window */
|
|
6
|
+
maxRequests: number;
|
|
7
|
+
/** Time window in milliseconds */
|
|
8
|
+
windowMs: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A sliding-window rate limiter that tracks requests per client.
|
|
12
|
+
* Uses a Map to store request timestamps for each client and
|
|
13
|
+
* automatically cleans up expired entries.
|
|
14
|
+
*/
|
|
15
|
+
export declare class RateLimiter {
|
|
16
|
+
private readonly maxRequests;
|
|
17
|
+
private readonly windowMs;
|
|
18
|
+
private readonly clients;
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new RateLimiter instance.
|
|
21
|
+
*
|
|
22
|
+
* @param config - Configuration for request limits and time window
|
|
23
|
+
* @throws Error if maxRequests or windowMs are not positive numbers
|
|
24
|
+
*/
|
|
25
|
+
constructor(config: RateLimiterConfig);
|
|
26
|
+
/**
|
|
27
|
+
* Checks if a request from the given client is allowed.
|
|
28
|
+
* If allowed, records the request timestamp.
|
|
29
|
+
*
|
|
30
|
+
* @param clientId - Unique identifier for the client
|
|
31
|
+
* @returns True if the request is allowed, false if rate limited
|
|
32
|
+
*/
|
|
33
|
+
isAllowed(clientId: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the number of remaining requests for a client within the current window.
|
|
36
|
+
*
|
|
37
|
+
* @param clientId - Unique identifier for the client
|
|
38
|
+
* @returns Number of remaining allowed requests
|
|
39
|
+
*/
|
|
40
|
+
getRemainingRequests(clientId: string): number;
|
|
41
|
+
/**
|
|
42
|
+
* Resets rate limiting state.
|
|
43
|
+
* If clientId is provided, resets only that client.
|
|
44
|
+
* Otherwise, resets all clients.
|
|
45
|
+
*
|
|
46
|
+
* @param clientId - Optional client identifier to reset
|
|
47
|
+
*/
|
|
48
|
+
reset(clientId?: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Removes expired timestamps from a client's entry.
|
|
51
|
+
* Deletes the entry entirely if no valid timestamps remain.
|
|
52
|
+
*
|
|
53
|
+
* @param clientId - Client identifier to clean up
|
|
54
|
+
* @param now - Current timestamp for expiration calculation
|
|
55
|
+
*/
|
|
56
|
+
private cleanupExpiredEntries;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=rate-limiter-simple.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter-simple.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limiter-simple.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;CAClB;AASD;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAE/D;;;;;OAKG;gBACS,MAAM,EAAE,iBAAiB;IAqBrC;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAmBpC;;;;;OAKG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAa9C;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ9B;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;CAgB9B"}
|