@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 +101 -48
- package/API.md +133 -133
- package/dist/adapters/mock/customer.d.ts +3 -1
- package/dist/adapters/mock/customer.js +18 -2
- package/dist/adapters/mock/mod.d.ts +2 -2
- package/dist/adapters/mock/mod.js +2 -2
- package/dist/adapters/mock/order.js +4 -4
- package/dist/adapters/mock/payment.d.ts +1 -1
- package/dist/adapters/mock/payment.js +32 -1
- package/dist/domains/base.js +1 -1
- package/dist/domains/cart.js +4 -1
- package/dist/domains/customer.d.ts +8 -0
- package/dist/domains/customer.js +47 -36
- package/dist/domains/mod.d.ts +2 -2
- package/dist/domains/mod.js +1 -1
- package/dist/domains/order.d.ts +3 -3
- package/dist/domains/order.js +9 -5
- package/dist/domains/payment.d.ts +28 -5
- package/dist/domains/payment.js +92 -3
- package/dist/mod.d.ts +1 -1
- package/dist/mod.js +1 -1
- package/dist/suite.d.ts +25 -2
- package/dist/suite.js +41 -1
- package/dist/types/adapter.d.ts +14 -6
- package/dist/types/events.d.ts +17 -3
- package/dist/types/state.d.ts +4 -12
- package/package.json +2 -2
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.
|
|
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
|
|
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 {
|
|
83
|
+
export { createECSuite, ECSuite, ECSuiteConfig } from "./suite.ts";
|
|
83
84
|
|
|
84
85
|
// Types
|
|
85
86
|
export {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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 (
|
|
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).
|