@marianmeres/ecsuite 1.1.4 → 1.2.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 CHANGED
@@ -6,7 +6,7 @@ Machine-readable documentation for AI coding assistants.
6
6
 
7
7
  ```yaml
8
8
  name: "@marianmeres/ecsuite"
9
- version: "1.1.1"
9
+ version: "1.1.4"
10
10
  type: "library"
11
11
  language: "typescript"
12
12
  runtime: "deno"
@@ -17,6 +17,7 @@ license: "MIT"
17
17
  ## Purpose
18
18
 
19
19
  E-commerce frontend UI state management library providing:
20
+
20
21
  - Optimistic updates with automatic rollback
21
22
  - Svelte-compatible reactive stores
22
23
  - Pluggable adapter pattern for server communication
@@ -29,9 +30,9 @@ E-commerce frontend UI state management library providing:
29
30
  ECSuite (orchestrator)
30
31
  ├── CartManager [localStorage, optimistic updates]
31
32
  ├── WishlistManager [localStorage, optimistic updates]
32
- ├── OrderManager [server-only, read + create]
33
- ├── CustomerManager [server-only, read + update]
34
- ├── PaymentManager [server-only, read-only]
33
+ ├── OrderManager [server-only, read + create (returns model_id)]
34
+ ├── CustomerManager [server-only, read + update + fetchBySession]
35
+ ├── PaymentManager [server-only, read + initiate + capture]
35
36
  └── ProductManager [in-memory cache with TTL]
36
37
  ```
37
38
 
@@ -79,36 +80,67 @@ tests/
79
80
 
80
81
  ```typescript
81
82
  // Main
82
- export { ECSuite, createECSuite, ECSuiteConfig } from "./suite.ts";
83
+ export { createECSuite, ECSuite, ECSuiteConfig } from "./suite.ts";
83
84
 
84
85
  // Types
85
86
  export {
86
- DomainState, DomainError, DomainStateWrapper, DomainContext,
87
- WishlistItem, WishlistData, EnrichedCartItem, EnrichedWishlistItem,
88
- CartAdapter, WishlistAdapter, OrderAdapter,
89
- CustomerAdapter, PaymentAdapter, ProductAdapter, OrderCreatePayload,
90
- DomainName, ECSuiteEventType, ECSuiteEvent, /* ...event interfaces */
87
+ CartAdapter,
88
+ CustomerAdapter,
89
+ DomainContext,
90
+ DomainError,
91
+ DomainName,
92
+ DomainState,
93
+ DomainStateWrapper,
94
+ ECSuiteEvent, /* ...event interfaces */
95
+ ECSuiteEventType,
96
+ EnrichedCartItem,
97
+ EnrichedWishlistItem,
98
+ OrderAdapter,
99
+ OrderCreatePayload,
100
+ OrderCreateResult,
101
+ PaymentAdapter,
102
+ PaymentInitConfig,
103
+ ProductAdapter,
104
+ WishlistAdapter,
105
+ WishlistData,
106
+ WishlistItem,
91
107
  } from "./types/mod.ts";
92
108
 
93
109
  // Domain Managers
94
110
  export {
95
- BaseDomainManager, BaseDomainOptions, StorageType,
96
- CartManager, CartManagerOptions,
97
- WishlistManager, WishlistManagerOptions,
98
- OrderManager, OrderManagerOptions, OrderListData,
99
- CustomerManager, CustomerManagerOptions,
100
- PaymentManager, PaymentManagerOptions, PaymentListData,
101
- ProductManager, ProductManagerOptions,
111
+ BaseDomainManager,
112
+ BaseDomainOptions,
113
+ CartManager,
114
+ CartManagerOptions,
115
+ CustomerManager,
116
+ CustomerManagerOptions,
117
+ OrderListData,
118
+ OrderManager,
119
+ OrderManagerOptions,
120
+ PaymentListData,
121
+ PaymentManager,
122
+ PaymentManagerOptions,
123
+ ProductManager,
124
+ ProductManagerOptions,
125
+ StorageType,
126
+ WishlistManager,
127
+ WishlistManagerOptions,
102
128
  } from "./domains/mod.ts";
103
129
 
104
130
  // Mock Adapters
105
131
  export {
106
- createMockCartAdapter, MockCartAdapterOptions,
107
- createMockWishlistAdapter, MockWishlistAdapterOptions,
108
- createMockOrderAdapter, MockOrderAdapterOptions,
109
- createMockCustomerAdapter, MockCustomerAdapterOptions,
110
- createMockPaymentAdapter, MockPaymentAdapterOptions,
111
- createMockProductAdapter, MockProductAdapterOptions,
132
+ createMockCartAdapter,
133
+ createMockCustomerAdapter,
134
+ createMockOrderAdapter,
135
+ createMockPaymentAdapter,
136
+ createMockProductAdapter,
137
+ createMockWishlistAdapter,
138
+ MockCartAdapterOptions,
139
+ MockCustomerAdapterOptions,
140
+ MockOrderAdapterOptions,
141
+ MockPaymentAdapterOptions,
142
+ MockProductAdapterOptions,
143
+ MockWishlistAdapterOptions,
112
144
  } from "./adapters/mod.ts";
113
145
  ```
114
146
 
@@ -129,11 +161,11 @@ State transitions:
129
161
 
130
162
  ```typescript
131
163
  const suite = createECSuite({
132
- context: { customerId: "uuid" },
133
- adapters: { cart: myCartAdapter },
134
- storage: { type: "local" },
135
- productCacheTtl: 300000,
136
- autoInitialize: true,
164
+ context: { customerId: "uuid" },
165
+ adapters: { cart: myCartAdapter },
166
+ storage: { type: "local" },
167
+ productCacheTtl: 300000,
168
+ autoInitialize: true,
137
169
  });
138
170
  ```
139
171
 
@@ -141,16 +173,26 @@ const suite = createECSuite({
141
173
 
142
174
  ```typescript
143
175
  suite.cart.subscribe((state) => {
144
- // state: { state, data, error, lastSyncedAt }
176
+ // state: { state, data, error, lastSyncedAt }
145
177
  });
146
178
  ```
147
179
 
148
180
  ### Event Handling
149
181
 
150
182
  ```typescript
151
- suite.on("cart:item:added", (event) => { /* ... */ });
152
- suite.onAny(({ event, data }) => { /* ... */ });
153
- suite.once("order:created", (event) => { /* ... */ });
183
+ suite.on("cart:item:added", (event) => {/* ... */});
184
+ suite.onAny(({ event, data }) => {/* ... */});
185
+ suite.once("order:created", (event) => {/* ... */});
186
+ ```
187
+
188
+ ### Operation Hooks
189
+
190
+ ```typescript
191
+ // Fire when any domain starts syncing
192
+ const unsub1 = suite.onBeforeSync(({ domain, previousState }) => {/* ... */});
193
+
194
+ // Fire when any domain completes or fails an operation
195
+ const unsub2 = suite.onAfterSync(({ domain, success, error }) => {/* ... */});
154
196
  ```
155
197
 
156
198
  ### Implementing Adapter
@@ -159,23 +201,25 @@ suite.once("order:created", (event) => { /* ... */ });
159
201
  import { HTTP_ERROR } from "@marianmeres/http-utils";
160
202
 
161
203
  const myAdapter: CartAdapter = {
162
- async fetch(ctx) {
163
- const res = await fetch(`/api/cart`);
164
- if (!res.ok) throw new HTTP_ERROR.BadRequest("Failed to fetch");
165
- return await res.json(); // returns CartData directly
166
- },
167
- // ... other methods throw HTTP_ERROR on failure
204
+ async fetch(ctx) {
205
+ const res = await fetch(`/api/cart`);
206
+ if (!res.ok) throw new HTTP_ERROR.BadRequest("Failed to fetch");
207
+ return await res.json(); // returns CartData directly
208
+ },
209
+ // ... other methods throw HTTP_ERROR on failure
168
210
  };
169
211
  ```
170
212
 
171
213
  ## Common Tasks
172
214
 
173
215
  ### Add New Domain
216
+
174
217
  1. Create manager in `src/domains/`
175
218
  2. Add adapter interface in `src/types/adapter.ts`
176
219
  3. Export from `mod.ts`
177
220
 
178
221
  ### Add New Event
222
+
179
223
  1. Add to `ECSuiteEventType` in `src/types/events.ts`
180
224
  2. Create interface in `src/types/events.ts`
181
225
 
@@ -183,25 +227,26 @@ const myAdapter: CartAdapter = {
183
227
 
184
228
  ```yaml
185
229
  runtime:
186
- "@marianmeres/clog": "^3.15.0"
187
- "@marianmeres/collection-types": "^1.9.0"
188
- "@marianmeres/http-utils": "^2.5.1"
189
- "@marianmeres/pubsub": "^2.4.5"
190
- "@marianmeres/store": "^2.4.2"
230
+ "@marianmeres/clog": "^3.15.0"
231
+ "@marianmeres/collection-types": "^1.9.0"
232
+ "@marianmeres/http-utils": "^2.5.1"
233
+ "@marianmeres/pubsub": "^2.4.5"
234
+ "@marianmeres/store": "^2.4.2"
191
235
  dev:
192
- "@std/assert": "^1.0.16"
193
- "@std/fs": "^1.0.20"
194
- "@std/path": "^1.1.3"
236
+ "@std/assert": "^1.0.16"
237
+ "@std/fs": "^1.0.20"
238
+ "@std/path": "^1.1.3"
195
239
  ```
196
240
 
197
241
  ## Testing
198
242
 
199
243
  ```bash
200
- deno test # Run all tests (93 tests)
244
+ deno test # Run all tests (109 tests)
201
245
  deno test --watch # Watch mode
202
246
  ```
203
247
 
204
248
  Test utilities:
249
+
205
250
  - Mock adapters with configurable delay and error injection
206
251
  - Memory storage type for isolated tests
207
252
 
@@ -230,4 +275,12 @@ deno publish # Publish to JSR
230
275
 
231
276
  4. **Event System**: Shared PubSub instance passed through ECSuite constructor. Events typed with discriminated union.
232
277
 
233
- 5. **Context**: DomainContext (customerId, sessionId) passed to all adapter methods for server-side identification.
278
+ 5. **Context**: DomainContext (customerId, sessionId, + arbitrary properties via index signature) passed to all adapter methods for server-side identification.
279
+
280
+ 6. **OrderCreateResult**: `OrderAdapter.create()` returns `{ model_id, data }` so consumers always get the server-assigned model ID.
281
+
282
+ 7. **Payment Write Ops**: `PaymentAdapter.initiate?()` and `capture?()` are optional methods. `PaymentManager` null-checks before calling, returns null when unavailable.
283
+
284
+ 8. **Guest Checkout**: `CustomerAdapter.fetchBySession?()` is optional. `CustomerManager` uses it when `customerId` is absent in context, falls back to `fetch()` when unavailable.
285
+
286
+ 9. **Operation Hooks**: `ECSuite.onBeforeSync()` and `onAfterSync()` are convenience wrappers over the existing event system (no changes to BaseDomainManager).