@marianmeres/ecsuite 1.0.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/AGENTS.md +218 -0
- package/API.md +865 -0
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/adapters/mock/cart.d.ts +20 -0
- package/dist/adapters/mock/cart.js +86 -0
- package/dist/adapters/mock/customer.d.ts +20 -0
- package/dist/adapters/mock/customer.js +58 -0
- package/dist/adapters/mock/mod.d.ts +9 -0
- package/dist/adapters/mock/mod.js +9 -0
- package/dist/adapters/mock/order.d.ts +20 -0
- package/dist/adapters/mock/order.js +66 -0
- package/dist/adapters/mock/payment.d.ts +20 -0
- package/dist/adapters/mock/payment.js +55 -0
- package/dist/adapters/mock/product.d.ts +25 -0
- package/dist/adapters/mock/product.js +60 -0
- package/dist/adapters/mock/wishlist.d.ts +20 -0
- package/dist/adapters/mock/wishlist.js +70 -0
- package/dist/adapters/mod.d.ts +6 -0
- package/dist/adapters/mod.js +6 -0
- package/dist/domains/base.d.ts +83 -0
- package/dist/domains/base.js +187 -0
- package/dist/domains/cart.d.ts +96 -0
- package/dist/domains/cart.js +287 -0
- package/dist/domains/customer.d.ts +74 -0
- package/dist/domains/customer.js +183 -0
- package/dist/domains/mod.d.ts +13 -0
- package/dist/domains/mod.js +13 -0
- package/dist/domains/order.d.ts +83 -0
- package/dist/domains/order.js +233 -0
- package/dist/domains/payment.d.ts +83 -0
- package/dist/domains/payment.js +175 -0
- package/dist/domains/product.d.ts +130 -0
- package/dist/domains/product.js +241 -0
- package/dist/domains/wishlist.d.ts +101 -0
- package/dist/domains/wishlist.js +256 -0
- package/dist/mod.d.ts +28 -0
- package/dist/mod.js +32 -0
- package/dist/suite.d.ts +115 -0
- package/dist/suite.js +168 -0
- package/dist/types/adapter.d.ts +77 -0
- package/dist/types/adapter.js +7 -0
- package/dist/types/events.d.ts +111 -0
- package/dist/types/events.js +7 -0
- package/dist/types/mod.d.ts +9 -0
- package/dist/types/mod.js +9 -0
- package/dist/types/state.d.ts +61 -0
- package/dist/types/state.js +7 -0
- package/package.json +28 -0
package/API.md
ADDED
|
@@ -0,0 +1,865 @@
|
|
|
1
|
+
# @marianmeres/ecsuite API Reference
|
|
2
|
+
|
|
3
|
+
Complete API documentation for the e-commerce frontend UI helper library.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [ECSuite](#ecsuite)
|
|
8
|
+
- [Domain Managers](#domain-managers)
|
|
9
|
+
- [CartManager](#cartmanager)
|
|
10
|
+
- [WishlistManager](#wishlistmanager)
|
|
11
|
+
- [OrderManager](#ordermanager)
|
|
12
|
+
- [CustomerManager](#customermanager)
|
|
13
|
+
- [PaymentManager](#paymentmanager)
|
|
14
|
+
- [ProductManager](#productmanager)
|
|
15
|
+
- [Adapter Interfaces](#adapter-interfaces)
|
|
16
|
+
- [Types](#types)
|
|
17
|
+
- [Events](#events)
|
|
18
|
+
- [Mock Adapters](#mock-adapters)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## ECSuite
|
|
23
|
+
|
|
24
|
+
Main orchestrator class that coordinates all domain managers.
|
|
25
|
+
|
|
26
|
+
### createECSuite(config?)
|
|
27
|
+
|
|
28
|
+
Factory function to create an ECSuite instance.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
function createECSuite(config?: ECSuiteConfig): ECSuite
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### ECSuiteConfig
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
interface ECSuiteConfig {
|
|
38
|
+
/** Initial context (customerId, sessionId) */
|
|
39
|
+
context?: DomainContext;
|
|
40
|
+
/** Adapters for server communication */
|
|
41
|
+
adapters?: {
|
|
42
|
+
cart?: CartAdapter;
|
|
43
|
+
wishlist?: WishlistAdapter;
|
|
44
|
+
order?: OrderAdapter;
|
|
45
|
+
customer?: CustomerAdapter;
|
|
46
|
+
payment?: PaymentAdapter;
|
|
47
|
+
product?: ProductAdapter;
|
|
48
|
+
};
|
|
49
|
+
/** Storage configuration */
|
|
50
|
+
storage?: {
|
|
51
|
+
/** Cart storage key (default: "ecsuite:cart") */
|
|
52
|
+
cartKey?: string;
|
|
53
|
+
/** Wishlist storage key (default: "ecsuite:wishlist") */
|
|
54
|
+
wishlistKey?: string;
|
|
55
|
+
/** Storage type for persisted domains (default: "local") */
|
|
56
|
+
type?: StorageType;
|
|
57
|
+
};
|
|
58
|
+
/** Product cache TTL in milliseconds (default: 5 minutes) */
|
|
59
|
+
productCacheTtl?: number;
|
|
60
|
+
/** Auto-initialize on creation (default: true) */
|
|
61
|
+
autoInitialize?: boolean;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### ECSuite Class
|
|
66
|
+
|
|
67
|
+
#### Properties
|
|
68
|
+
|
|
69
|
+
| Property | Type | Description |
|
|
70
|
+
|----------|------|-------------|
|
|
71
|
+
| `cart` | `CartManager` | Cart domain manager |
|
|
72
|
+
| `wishlist` | `WishlistManager` | Wishlist domain manager |
|
|
73
|
+
| `order` | `OrderManager` | Order domain manager |
|
|
74
|
+
| `customer` | `CustomerManager` | Customer domain manager |
|
|
75
|
+
| `payment` | `PaymentManager` | Payment domain manager |
|
|
76
|
+
| `product` | `ProductManager` | Product domain manager |
|
|
77
|
+
|
|
78
|
+
#### Methods
|
|
79
|
+
|
|
80
|
+
##### initialize()
|
|
81
|
+
|
|
82
|
+
Initialize all domains. Called automatically if `autoInitialize` is true.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
async initialize(): Promise<void>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
##### setContext(context)
|
|
89
|
+
|
|
90
|
+
Update context across all domains.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
setContext(context: DomainContext): void
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
##### getContext()
|
|
97
|
+
|
|
98
|
+
Get the current context.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
getContext(): DomainContext
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
##### on(eventType, callback)
|
|
105
|
+
|
|
106
|
+
Subscribe to a specific event type.
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
on(eventType: ECSuiteEventType, callback: Subscriber): Unsubscriber
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
##### onAny(callback)
|
|
113
|
+
|
|
114
|
+
Subscribe to all events.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
onAny(callback: (envelope: { event: string; data: ECSuiteEvent }) => void): Unsubscriber
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
##### once(eventType, callback)
|
|
121
|
+
|
|
122
|
+
Subscribe once to an event.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
once(eventType: ECSuiteEventType, callback: Subscriber): Unsubscriber
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
##### reset()
|
|
129
|
+
|
|
130
|
+
Reset all domains to initial state.
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
reset(): void
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Domain Managers
|
|
139
|
+
|
|
140
|
+
All domain managers share a common interface:
|
|
141
|
+
|
|
142
|
+
- `subscribe(callback)` - Svelte-compatible store subscription
|
|
143
|
+
- `get()` - Get current state synchronously
|
|
144
|
+
- `setAdapter(adapter)` - Set the adapter
|
|
145
|
+
- `getAdapter()` - Get the adapter (may be null)
|
|
146
|
+
- `setContext(context)` - Update context
|
|
147
|
+
- `getContext()` - Get current context
|
|
148
|
+
- `initialize()` - Initialize the domain
|
|
149
|
+
- `reset()` - Reset to initial state
|
|
150
|
+
|
|
151
|
+
### State Wrapper
|
|
152
|
+
|
|
153
|
+
All domains wrap their data in `DomainStateWrapper<T>`:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
interface DomainStateWrapper<T> {
|
|
157
|
+
state: DomainState; // "initializing" | "ready" | "syncing" | "error"
|
|
158
|
+
data: T | null; // Domain data
|
|
159
|
+
error: DomainError | null; // Error info when state is "error"
|
|
160
|
+
lastSyncedAt: number | null; // Timestamp of last sync
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### CartManager
|
|
167
|
+
|
|
168
|
+
Manages shopping cart with localStorage persistence and optimistic updates.
|
|
169
|
+
|
|
170
|
+
#### Constructor Options
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
interface CartManagerOptions {
|
|
174
|
+
adapter?: CartAdapter;
|
|
175
|
+
storageKey?: string; // default: "ecsuite:cart"
|
|
176
|
+
storageType?: StorageType; // default: "local"
|
|
177
|
+
context?: DomainContext;
|
|
178
|
+
pubsub?: PubSub;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Methods
|
|
183
|
+
|
|
184
|
+
##### addItem(item)
|
|
185
|
+
|
|
186
|
+
Add item to cart. Increments quantity if product already exists.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
async addItem(item: CartItem): Promise<void>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Emits:** `cart:item:added`
|
|
193
|
+
|
|
194
|
+
##### updateItemQuantity(productId, quantity)
|
|
195
|
+
|
|
196
|
+
Update item quantity. Removes item if quantity <= 0.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
async updateItemQuantity(productId: UUID, quantity: number): Promise<void>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Emits:** `cart:item:updated`
|
|
203
|
+
|
|
204
|
+
##### removeItem(productId)
|
|
205
|
+
|
|
206
|
+
Remove item from cart.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
async removeItem(productId: UUID): Promise<void>
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Emits:** `cart:item:removed`
|
|
213
|
+
|
|
214
|
+
##### clear()
|
|
215
|
+
|
|
216
|
+
Clear all items from cart.
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
async clear(): Promise<void>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Emits:** `cart:cleared`
|
|
223
|
+
|
|
224
|
+
##### getItemCount()
|
|
225
|
+
|
|
226
|
+
Get total item count (sum of all quantities).
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
getItemCount(): number
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
##### hasProduct(productId)
|
|
233
|
+
|
|
234
|
+
Check if product is in cart.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
hasProduct(productId: UUID): boolean
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
##### getItem(productId)
|
|
241
|
+
|
|
242
|
+
Get cart item by product ID.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
getItem(productId: UUID): CartItem | undefined
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
##### getEnrichedItems(productManager)
|
|
249
|
+
|
|
250
|
+
Get cart items with product data and line totals.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
async getEnrichedItems(productManager: ProductManager): Promise<EnrichedCartItem[]>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
### WishlistManager
|
|
259
|
+
|
|
260
|
+
Manages wishlist with localStorage persistence and optimistic updates.
|
|
261
|
+
|
|
262
|
+
#### Constructor Options
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
interface WishlistManagerOptions {
|
|
266
|
+
adapter?: WishlistAdapter;
|
|
267
|
+
storageKey?: string; // default: "ecsuite:wishlist"
|
|
268
|
+
storageType?: StorageType; // default: "local"
|
|
269
|
+
context?: DomainContext;
|
|
270
|
+
pubsub?: PubSub;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Methods
|
|
275
|
+
|
|
276
|
+
##### addItem(productId)
|
|
277
|
+
|
|
278
|
+
Add product to wishlist. No-op if already present.
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
async addItem(productId: UUID): Promise<void>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Emits:** `wishlist:item:added`
|
|
285
|
+
|
|
286
|
+
##### removeItem(productId)
|
|
287
|
+
|
|
288
|
+
Remove product from wishlist.
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
async removeItem(productId: UUID): Promise<void>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Emits:** `wishlist:item:removed`
|
|
295
|
+
|
|
296
|
+
##### toggleItem(productId)
|
|
297
|
+
|
|
298
|
+
Toggle product in wishlist. Returns true if added, false if removed.
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
async toggleItem(productId: UUID): Promise<boolean>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
##### clear()
|
|
305
|
+
|
|
306
|
+
Clear all items from wishlist.
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
async clear(): Promise<void>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Emits:** `wishlist:cleared`
|
|
313
|
+
|
|
314
|
+
##### getItemCount()
|
|
315
|
+
|
|
316
|
+
Get number of items in wishlist.
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
getItemCount(): number
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
##### hasProduct(productId)
|
|
323
|
+
|
|
324
|
+
Check if product is in wishlist.
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
hasProduct(productId: UUID): boolean
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
##### getItem(productId)
|
|
331
|
+
|
|
332
|
+
Get wishlist item by product ID.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
getItem(productId: UUID): WishlistItem | undefined
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
##### getProductIds()
|
|
339
|
+
|
|
340
|
+
Get all product IDs in wishlist.
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
getProductIds(): UUID[]
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
##### getEnrichedItems(productManager)
|
|
347
|
+
|
|
348
|
+
Get wishlist items with product data.
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
async getEnrichedItems(productManager: ProductManager): Promise<EnrichedWishlistItem[]>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
### OrderManager
|
|
357
|
+
|
|
358
|
+
Manages orders with server-side data source (no local persistence).
|
|
359
|
+
|
|
360
|
+
#### Constructor Options
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
interface OrderManagerOptions {
|
|
364
|
+
adapter?: OrderAdapter;
|
|
365
|
+
context?: DomainContext;
|
|
366
|
+
pubsub?: PubSub;
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
#### Methods
|
|
371
|
+
|
|
372
|
+
##### fetchAll()
|
|
373
|
+
|
|
374
|
+
Fetch all orders from server.
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
async fetchAll(): Promise<void>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Emits:** `order:fetched`
|
|
381
|
+
|
|
382
|
+
##### fetchOne(orderId)
|
|
383
|
+
|
|
384
|
+
Fetch single order by ID.
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
async fetchOne(orderId: UUID): Promise<OrderData | null>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
##### create(orderData)
|
|
391
|
+
|
|
392
|
+
Create a new order.
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
async create(orderData: OrderCreatePayload): Promise<OrderData | null>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Emits:** `order:created`
|
|
399
|
+
|
|
400
|
+
##### getOrderCount()
|
|
401
|
+
|
|
402
|
+
Get total number of orders.
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
getOrderCount(): number
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
##### getOrders()
|
|
409
|
+
|
|
410
|
+
Get all orders.
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
getOrders(): OrderData[]
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
##### getOrderByIndex(index)
|
|
417
|
+
|
|
418
|
+
Get order by index.
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
getOrderByIndex(index: number): OrderData | undefined
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
### CustomerManager
|
|
427
|
+
|
|
428
|
+
Manages customer profile with server-side data source.
|
|
429
|
+
|
|
430
|
+
#### Constructor Options
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
interface CustomerManagerOptions {
|
|
434
|
+
adapter?: CustomerAdapter;
|
|
435
|
+
context?: DomainContext;
|
|
436
|
+
pubsub?: PubSub;
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
#### Methods
|
|
441
|
+
|
|
442
|
+
##### refresh()
|
|
443
|
+
|
|
444
|
+
Refresh customer data from server.
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
async refresh(): Promise<void>
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**Emits:** `customer:fetched`
|
|
451
|
+
|
|
452
|
+
##### update(data)
|
|
453
|
+
|
|
454
|
+
Update customer data with optimistic update.
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
async update(data: Partial<CustomerData>): Promise<void>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
**Emits:** `customer:updated`
|
|
461
|
+
|
|
462
|
+
##### getEmail()
|
|
463
|
+
|
|
464
|
+
Get customer email.
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
getEmail(): string | null
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
##### getName()
|
|
471
|
+
|
|
472
|
+
Get customer name.
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
getName(): string | null
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
##### isGuest()
|
|
479
|
+
|
|
480
|
+
Check if customer is a guest.
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
isGuest(): boolean
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
##### hasData()
|
|
487
|
+
|
|
488
|
+
Check if customer data is loaded.
|
|
489
|
+
|
|
490
|
+
```typescript
|
|
491
|
+
hasData(): boolean
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
### PaymentManager
|
|
497
|
+
|
|
498
|
+
Manages payment data with server-side source (read-only).
|
|
499
|
+
|
|
500
|
+
#### Constructor Options
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
interface PaymentManagerOptions {
|
|
504
|
+
adapter?: PaymentAdapter;
|
|
505
|
+
context?: DomainContext;
|
|
506
|
+
pubsub?: PubSub;
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
#### Methods
|
|
511
|
+
|
|
512
|
+
##### fetchForOrder(orderId)
|
|
513
|
+
|
|
514
|
+
Fetch payments for a specific order.
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
async fetchForOrder(orderId: UUID): Promise<PaymentData[]>
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
**Emits:** `payment:fetched`
|
|
521
|
+
|
|
522
|
+
##### fetchOne(paymentId)
|
|
523
|
+
|
|
524
|
+
Fetch single payment by ID.
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
async fetchOne(paymentId: UUID): Promise<PaymentData | null>
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
##### getPaymentCount()
|
|
531
|
+
|
|
532
|
+
Get number of fetched payments.
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
getPaymentCount(): number
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
##### getPayments()
|
|
539
|
+
|
|
540
|
+
Get all fetched payments.
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
getPayments(): PaymentData[]
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
##### getPaymentByRef(providerReference)
|
|
547
|
+
|
|
548
|
+
Get payment by provider reference.
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
getPaymentByRef(providerReference: string): PaymentData | undefined
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
##### clearCache()
|
|
555
|
+
|
|
556
|
+
Clear local payment cache.
|
|
557
|
+
|
|
558
|
+
```typescript
|
|
559
|
+
clearCache(): void
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
### ProductManager
|
|
565
|
+
|
|
566
|
+
Manages product data with in-memory caching. Unlike other managers, uses a simple cache layer instead of state machine.
|
|
567
|
+
|
|
568
|
+
#### Constructor Options
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
interface ProductManagerOptions {
|
|
572
|
+
adapter?: ProductAdapter;
|
|
573
|
+
context?: DomainContext;
|
|
574
|
+
pubsub?: PubSub;
|
|
575
|
+
cacheTtl?: number; // default: 5 minutes
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
#### Methods
|
|
580
|
+
|
|
581
|
+
##### getById(productId)
|
|
582
|
+
|
|
583
|
+
Get single product by ID. Returns from cache if valid.
|
|
584
|
+
|
|
585
|
+
```typescript
|
|
586
|
+
async getById(productId: UUID): Promise<ProductData | null>
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
**Emits:** `product:fetched` (on server fetch)
|
|
590
|
+
|
|
591
|
+
##### getByIds(productIds)
|
|
592
|
+
|
|
593
|
+
Get multiple products by IDs. Uses batch fetch for missing items.
|
|
594
|
+
|
|
595
|
+
```typescript
|
|
596
|
+
async getByIds(productIds: UUID[]): Promise<Map<UUID, ProductData>>
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
**Emits:** `product:fetched` (for each server fetch)
|
|
600
|
+
|
|
601
|
+
##### prefetch(productIds)
|
|
602
|
+
|
|
603
|
+
Prefetch products into cache.
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
async prefetch(productIds: UUID[]): Promise<void>
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
##### isCached(productId)
|
|
610
|
+
|
|
611
|
+
Check if product is in cache and not expired.
|
|
612
|
+
|
|
613
|
+
```typescript
|
|
614
|
+
isCached(productId: UUID): boolean
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
##### getCacheSize()
|
|
618
|
+
|
|
619
|
+
Get number of cached products.
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
getCacheSize(): number
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
##### clearCache(productId?)
|
|
626
|
+
|
|
627
|
+
Clear cache entirely or for specific product.
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
clearCache(productId?: UUID): void
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
---
|
|
634
|
+
|
|
635
|
+
## Adapter Interfaces
|
|
636
|
+
|
|
637
|
+
### AdapterResult<T>
|
|
638
|
+
|
|
639
|
+
All adapter methods return this result type:
|
|
640
|
+
|
|
641
|
+
```typescript
|
|
642
|
+
interface AdapterResult<T> {
|
|
643
|
+
success: boolean;
|
|
644
|
+
data?: T;
|
|
645
|
+
error?: {
|
|
646
|
+
code: string;
|
|
647
|
+
message: string;
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### CartAdapter
|
|
653
|
+
|
|
654
|
+
```typescript
|
|
655
|
+
interface CartAdapter {
|
|
656
|
+
fetch(ctx: DomainContext): Promise<AdapterResult<CartData>>;
|
|
657
|
+
addItem(item: CartItem, ctx: DomainContext): Promise<AdapterResult<CartData>>;
|
|
658
|
+
updateItem(productId: UUID, quantity: number, ctx: DomainContext): Promise<AdapterResult<CartData>>;
|
|
659
|
+
removeItem(productId: UUID, ctx: DomainContext): Promise<AdapterResult<CartData>>;
|
|
660
|
+
clear(ctx: DomainContext): Promise<AdapterResult<CartData>>;
|
|
661
|
+
sync(cart: CartData, ctx: DomainContext): Promise<AdapterResult<CartData>>;
|
|
662
|
+
}
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
### WishlistAdapter
|
|
666
|
+
|
|
667
|
+
```typescript
|
|
668
|
+
interface WishlistAdapter {
|
|
669
|
+
fetch(ctx: DomainContext): Promise<AdapterResult<WishlistData>>;
|
|
670
|
+
addItem(productId: UUID, ctx: DomainContext): Promise<AdapterResult<WishlistData>>;
|
|
671
|
+
removeItem(productId: UUID, ctx: DomainContext): Promise<AdapterResult<WishlistData>>;
|
|
672
|
+
clear(ctx: DomainContext): Promise<AdapterResult<WishlistData>>;
|
|
673
|
+
sync(wishlist: WishlistData, ctx: DomainContext): Promise<AdapterResult<WishlistData>>;
|
|
674
|
+
}
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
### OrderAdapter
|
|
678
|
+
|
|
679
|
+
```typescript
|
|
680
|
+
interface OrderAdapter {
|
|
681
|
+
fetchAll(ctx: DomainContext): Promise<AdapterResult<OrderData[]>>;
|
|
682
|
+
fetchOne(orderId: UUID, ctx: DomainContext): Promise<AdapterResult<OrderData>>;
|
|
683
|
+
create(order: OrderCreatePayload, ctx: DomainContext): Promise<AdapterResult<OrderData>>;
|
|
684
|
+
}
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
### CustomerAdapter
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
interface CustomerAdapter {
|
|
691
|
+
fetch(ctx: DomainContext): Promise<AdapterResult<CustomerData>>;
|
|
692
|
+
update(data: Partial<CustomerData>, ctx: DomainContext): Promise<AdapterResult<CustomerData>>;
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
### PaymentAdapter
|
|
697
|
+
|
|
698
|
+
```typescript
|
|
699
|
+
interface PaymentAdapter {
|
|
700
|
+
fetchForOrder(orderId: UUID, ctx: DomainContext): Promise<AdapterResult<PaymentData[]>>;
|
|
701
|
+
fetchOne(paymentId: UUID, ctx: DomainContext): Promise<AdapterResult<PaymentData>>;
|
|
702
|
+
}
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### ProductAdapter
|
|
706
|
+
|
|
707
|
+
```typescript
|
|
708
|
+
interface ProductAdapter {
|
|
709
|
+
fetchOne(productId: UUID, ctx: DomainContext): Promise<AdapterResult<ProductData>>;
|
|
710
|
+
fetchMany(productIds: UUID[], ctx: DomainContext): Promise<AdapterResult<ProductData[]>>;
|
|
711
|
+
}
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
## Types
|
|
717
|
+
|
|
718
|
+
### DomainState
|
|
719
|
+
|
|
720
|
+
```typescript
|
|
721
|
+
type DomainState = "initializing" | "ready" | "syncing" | "error";
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
### DomainContext
|
|
725
|
+
|
|
726
|
+
```typescript
|
|
727
|
+
interface DomainContext {
|
|
728
|
+
customerId?: UUID;
|
|
729
|
+
sessionId?: UUID;
|
|
730
|
+
}
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### DomainError
|
|
734
|
+
|
|
735
|
+
```typescript
|
|
736
|
+
interface DomainError {
|
|
737
|
+
code: string;
|
|
738
|
+
message: string;
|
|
739
|
+
operation: string;
|
|
740
|
+
originalError?: unknown;
|
|
741
|
+
}
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### StorageType
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
type StorageType = "local" | "session" | "memory" | null;
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
### WishlistItem
|
|
751
|
+
|
|
752
|
+
```typescript
|
|
753
|
+
interface WishlistItem {
|
|
754
|
+
product_id: UUID;
|
|
755
|
+
added_at?: number;
|
|
756
|
+
}
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
### WishlistData
|
|
760
|
+
|
|
761
|
+
```typescript
|
|
762
|
+
interface WishlistData {
|
|
763
|
+
items: WishlistItem[];
|
|
764
|
+
}
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
### EnrichedCartItem
|
|
768
|
+
|
|
769
|
+
```typescript
|
|
770
|
+
interface EnrichedCartItem extends CartItem {
|
|
771
|
+
product: ProductData | null;
|
|
772
|
+
lineTotal: number;
|
|
773
|
+
}
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### EnrichedWishlistItem
|
|
777
|
+
|
|
778
|
+
```typescript
|
|
779
|
+
interface EnrichedWishlistItem extends WishlistItem {
|
|
780
|
+
product: ProductData | null;
|
|
781
|
+
}
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
---
|
|
785
|
+
|
|
786
|
+
## Events
|
|
787
|
+
|
|
788
|
+
### Event Types
|
|
789
|
+
|
|
790
|
+
| Event | Description |
|
|
791
|
+
|-------|-------------|
|
|
792
|
+
| `domain:state:changed` | Domain state transitioned |
|
|
793
|
+
| `domain:error` | Domain operation failed |
|
|
794
|
+
| `domain:synced` | Domain successfully synced |
|
|
795
|
+
| `cart:item:added` | Cart item added |
|
|
796
|
+
| `cart:item:updated` | Cart item quantity updated |
|
|
797
|
+
| `cart:item:removed` | Cart item removed |
|
|
798
|
+
| `cart:cleared` | Cart cleared |
|
|
799
|
+
| `wishlist:item:added` | Wishlist item added |
|
|
800
|
+
| `wishlist:item:removed` | Wishlist item removed |
|
|
801
|
+
| `wishlist:cleared` | Wishlist cleared |
|
|
802
|
+
| `order:created` | Order created |
|
|
803
|
+
| `order:fetched` | Orders fetched |
|
|
804
|
+
| `customer:updated` | Customer updated |
|
|
805
|
+
| `customer:fetched` | Customer fetched |
|
|
806
|
+
| `payment:fetched` | Payments fetched |
|
|
807
|
+
| `product:fetched` | Product fetched |
|
|
808
|
+
|
|
809
|
+
### Event Interfaces
|
|
810
|
+
|
|
811
|
+
All events extend `ECSuiteEventBase`:
|
|
812
|
+
|
|
813
|
+
```typescript
|
|
814
|
+
interface ECSuiteEventBase {
|
|
815
|
+
timestamp: number;
|
|
816
|
+
domain: DomainName;
|
|
817
|
+
}
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
---
|
|
821
|
+
|
|
822
|
+
## Mock Adapters
|
|
823
|
+
|
|
824
|
+
Mock adapters are provided for testing:
|
|
825
|
+
|
|
826
|
+
```typescript
|
|
827
|
+
import {
|
|
828
|
+
createMockCartAdapter,
|
|
829
|
+
createMockWishlistAdapter,
|
|
830
|
+
createMockOrderAdapter,
|
|
831
|
+
createMockCustomerAdapter,
|
|
832
|
+
createMockPaymentAdapter,
|
|
833
|
+
createMockProductAdapter,
|
|
834
|
+
} from "@marianmeres/ecsuite";
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### Mock Adapter Options
|
|
838
|
+
|
|
839
|
+
All mock adapters support:
|
|
840
|
+
|
|
841
|
+
```typescript
|
|
842
|
+
interface MockAdapterOptions {
|
|
843
|
+
initialData?: T; // Initial data
|
|
844
|
+
delay?: number; // Network delay in ms (default: 50)
|
|
845
|
+
forceError?: { // Force errors for testing
|
|
846
|
+
operation?: string;
|
|
847
|
+
code?: string;
|
|
848
|
+
message?: string;
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
### Example
|
|
854
|
+
|
|
855
|
+
```typescript
|
|
856
|
+
const suite = createECSuite({
|
|
857
|
+
adapters: {
|
|
858
|
+
cart: createMockCartAdapter({
|
|
859
|
+
initialData: { items: [{ product_id: "p1", quantity: 2 }] },
|
|
860
|
+
delay: 100,
|
|
861
|
+
}),
|
|
862
|
+
},
|
|
863
|
+
storage: { type: "memory" },
|
|
864
|
+
});
|
|
865
|
+
```
|