@use-stall/core 0.0.1 → 0.0.3

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 ADDED
@@ -0,0 +1,477 @@
1
+ # Stall Core SDK
2
+
3
+ A universal, type-safe, adapter-based SDK for integrating multiple e-commerce connectors (WooCommerce, Shopify, Medusa, etc.) with a unified interface. The SDK uses a dynamic adapter architecture with IndexedDB caching for optimal performance.
4
+
5
+ ## Overview
6
+
7
+ The Stall Core SDK provides an adapter-based architecture that allows you to:
8
+
9
+ - **Load connector adapters dynamically** from a remote URL with automatic caching
10
+ - **Standardize operations** across different e-commerce platforms
11
+ - **Work with unified types** for products, orders, customers, inventory, and more
12
+ - **Implement CRUD + bulk operations** with a consistent API
13
+ - **Handle errors gracefully** with try-catch wrapped operations
14
+ - **Cache adapter modules** in IndexedDB with TTL-based invalidation
15
+
16
+ ## Architecture
17
+
18
+ ```
19
+ ┌─────────────────────────────────────┐
20
+ │ Your Application │
21
+ └──────────────┬──────────────────────┘
22
+
23
+ ┌───────▼──────────────────┐
24
+ │ initializeStallCore()
25
+ │ Returns: CoreConfig
26
+ └───────┬──────────────────┘
27
+
28
+ ┌──────────▼──────────┐
29
+ │ Service Layer │
30
+ ├─────────────────────┤
31
+ │ - products │
32
+ │ - orders │
33
+ │ - customers │
34
+ │ - variants │
35
+ │ - inventory_levels │
36
+ │ - promotions │
37
+ │ - refunds │
38
+ │ - payments │
39
+ │ - tax_regions │
40
+ │ - locations │
41
+ │ - fulfillments │
42
+ │ - ... and more │
43
+ └──────────┬──────────┘
44
+
45
+ ┌──────────▼──────────────────┐
46
+ │ Adapter Module (Cached) │
47
+ │ ┌───────────────────────┐ │
48
+ │ │ - Products module │ │
49
+ │ │ - Orders module │ │
50
+ │ │ - Customers module │ │
51
+ │ │ - All modules │ │
52
+ │ └───────────────────────┘ │
53
+ │ │
54
+ │ Storage: IndexedDB + Dexie │
55
+ │ TTL: 4 hours (configurable)│
56
+ └──────────┬──────────────────┘
57
+
58
+ ┌──────────▼──────────────────┐
59
+ │ Connector Loader │
60
+ │ (Dynamic Module Import) │
61
+ └──────────┬──────────────────┘
62
+
63
+ ┌──────────▼──────────────────┐
64
+ │ Commerce Platform API │
65
+ │ (WooCommerce, Shopify, │
66
+ │ Medusa,Google Sheets etc.) │
67
+ └─────────────────────────────┘
68
+ ```
69
+
70
+ ## Installation
71
+
72
+ ```bash
73
+ bun install @use-stall/core
74
+ ```
75
+
76
+ ## Quick Start
77
+
78
+ ### Initialize the SDK
79
+
80
+ ```typescript
81
+ import { initializeStallCore, products, orders, customers } from '@use-stall/core';
82
+
83
+ // Initialize with connector configuration
84
+ const stall = initializeStallCore({
85
+ connector_url: 'https://connectors.myapp.xyz/woocommerce',
86
+ version: '1.0.0',
87
+ configuration: {
88
+ endpoint: 'https://myshop.com',
89
+ token: process.env.WOOCOMMERCE_TOKEN,
90
+ },
91
+ });
92
+ ```
93
+
94
+ ### Use Any Service
95
+
96
+ ```typescript
97
+ try {
98
+ // Products
99
+ const productList = await products.list({ sdk: stall, query: 'laptop' });
100
+ const product = await products.retrieve({ sdk: stall, id: 'prod_123' });
101
+ const newProduct = await products.create({
102
+ sdk: stall,
103
+ data: { name: 'New Product', price: 99.99 }
104
+ });
105
+ const updated = await products.update({
106
+ sdk: stall,
107
+ id: 'prod_123',
108
+ data: { price: 89.99 }
109
+ });
110
+ await products.delete({ sdk: stall, id: 'prod_123' });
111
+
112
+ // Bulk operations
113
+ const created = await products.bulk_create({
114
+ sdk: stall,
115
+ data: [{ name: 'Product 1' }, { name: 'Product 2' }]
116
+ });
117
+ const updated = await products.bulk_update({
118
+ sdk: stall,
119
+ data: [
120
+ { id: 'prod_1', data: { name: 'Updated 1' } },
121
+ { id: 'prod_2', data: { name: 'Updated 2' } },
122
+ ]
123
+ });
124
+ await products.bulk_delete({ sdk: stall, ids: ['prod_1', 'prod_2'] });
125
+ } catch (error) {
126
+ console.error('Operation failed:', error);
127
+ }
128
+ ```
129
+
130
+ ## Available Services
131
+
132
+ ### Core CRUD Operations
133
+
134
+ Each service module provides 8 standard operations:
135
+
136
+ - **list(props)** - Get array of items with query search
137
+ - **retrieve(props)** - Get single item by ID
138
+ - **create(props)** - Create new item
139
+ - **update(props)** - Update existing item
140
+ - **delete(props)** - Delete item by ID
141
+ - **bulk_create(props)** - Create multiple items
142
+ - **bulk_update(props)** - Update multiple items
143
+ - **bulk_delete(props)** - Delete multiple items
144
+
145
+ ### Inventory & Catalog
146
+
147
+ ```typescript
148
+ // Products
149
+ const productList = await products.list({ sdk: stall, query: 'laptop' });
150
+ const product = await products.retrieve({ sdk: stall, id: 'prod_123' });
151
+ const newProduct = await products.create({ sdk: stall, data: { name: 'New Product' } });
152
+ const updated = await products.update({ sdk: stall, id: 'prod_123', data: { price: 99.99 } });
153
+ await products.delete({ sdk: stall, id: 'prod_123' });
154
+ const bulkProducts = await products.bulk_create({ sdk: stall, data: [...] });
155
+ const updatedBulk = await products.bulk_update({ sdk: stall, data: [...] });
156
+ await products.bulk_delete({ sdk: stall, ids: ['prod_1', 'prod_2'] });
157
+
158
+ // Variants
159
+ const variantList = await variants.list({ sdk: stall, query: 'color-red' });
160
+ const variant = await variants.retrieve({ sdk: stall, id: 'var_123' });
161
+
162
+ // Categories
163
+ const categoryList = await categories.list({ sdk: stall, query: 'electronics' });
164
+ const category = await categories.retrieve({ sdk: stall, id: 'cat_123' });
165
+
166
+ // Collections
167
+ const collectionList = await collections.list({ sdk: stall, query: 'featured' });
168
+ const collection = await collections.retrieve({ sdk: stall, id: 'coll_123' });
169
+ const newCollection = await collections.create({ sdk: stall, data: { title: 'Summer Sale' } });
170
+
171
+ // Inventory Levels
172
+ const inventoryList = await inventory_levels.list({ sdk: stall, query: 'low' });
173
+ const inventory = await inventory_levels.retrieve({ sdk: stall, id: 'inv_123' });
174
+ const newInventory = await inventory_levels.create({ sdk: stall, data: { quantity: 100 } });
175
+ const updatedInventory = await inventory_levels.update({ sdk: stall, id: 'inv_123', data: { quantity: 150 } });
176
+ await inventory_levels.delete({ sdk: stall, id: 'inv_123' });
177
+ const bulkInventory = await inventory_levels.bulk_create({ sdk: stall, data: [...] });
178
+ const updatedBulkInventory = await inventory_levels.bulk_update({ sdk: stall, data: [...] });
179
+ await inventory_levels.bulk_delete({ sdk: stall, ids: ['inv_1', 'inv_2'] });
180
+ ```
181
+
182
+ ### Order Management
183
+
184
+ ```typescript
185
+ // Orders
186
+ const orderList = await orders.list({ sdk: stall, query: 'pending' });
187
+ const order = await orders.retrieve({ sdk: stall, id: 'order_123' });
188
+ const newOrder = await orders.create({ sdk: stall, data: { customer_id: 'cust_123' } });
189
+ const updatedOrder = await orders.update({ sdk: stall, id: 'order_123', data: { status: 'shipped' } });
190
+ await orders.delete({ sdk: stall, id: 'order_123' });
191
+
192
+ // Order Notes
193
+ const noteList = await order_notes.list({ sdk: stall, query: 'urgent' });
194
+ const note = await order_notes.retrieve({ sdk: stall, id: 'note_123' });
195
+ const newNote = await order_notes.create({ sdk: stall, data: { text: 'Handle with care' } });
196
+
197
+ // Refunds
198
+ const refundList = await refunds.list({ sdk: stall, query: 'pending' });
199
+ const refund = await refunds.retrieve({ sdk: stall, id: 'ref_123' });
200
+ const newRefund = await refunds.create({ sdk: stall, data: { amount: 99.99 } });
201
+ ```
202
+
203
+ ### Customer Management
204
+
205
+ ```typescript
206
+ // Customers
207
+ const customers_list = await customers.list({ sdk: stall, query: 'john' });
208
+ const customer = await customers.retrieve({ sdk: stall, id: 'cust_123' });
209
+ const newCustomer = await customers.create({ sdk: stall, data: { email: 'john@example.com' } });
210
+ const updatedCustomer = await customers.update({ sdk: stall, id: 'cust_123', data: { phone: '+1234567890' } });
211
+ await customers.delete({ sdk: stall, id: 'cust_123' });
212
+ ```
213
+
214
+ ### Promotions
215
+
216
+ ```typescript
217
+ // Promotions
218
+ const promotionList = await promotions.list({ sdk: stall, query: 'active' });
219
+ const promotion = await promotions.retrieve({ sdk: stall, id: 'promo_123' });
220
+ const newPromotion = await promotions.create({ sdk: stall, data: { code: 'SUMMER20' } });
221
+ ```
222
+
223
+ ### Payment Management
224
+
225
+ ```typescript
226
+ // Payment Providers
227
+ const providerList = await payment_providers.list({ sdk: stall, query: 'stripe' });
228
+ const provider = await payment_providers.retrieve({ sdk: stall, id: 'pay_prov_123' });
229
+ const newProvider = await payment_providers.create({ sdk: stall, data: { name: 'PayPal' } });
230
+ const updatedProvider = await payment_providers.update({ sdk: stall, id: 'pay_prov_123', data: { status: 'active' } });
231
+ await payment_providers.delete({ sdk: stall, id: 'pay_prov_123' });
232
+
233
+ // Payments
234
+ const paymentList = await payments.list({ sdk: stall, query: 'successful' });
235
+ const payment = await payments.retrieve({ sdk: stall, id: 'pay_123' });
236
+ const newPayment = await payments.create({ sdk: stall, data: { amount: 199.99 } });
237
+ ```
238
+
239
+ ### Tax & Location
240
+
241
+ ```typescript
242
+ // Tax Regions
243
+ const taxRegionList = await tax_regions.list({ sdk: stall, query: 'US' });
244
+ const taxRegion = await tax_regions.retrieve({ sdk: stall, id: 'tax_reg_123' });
245
+ const newTaxRegion = await tax_regions.create({ sdk: stall, data: { country: 'US' } });
246
+
247
+ // Tax Rates
248
+ const taxRateList = await tax_rates.list({ sdk: stall, query: 'standard' });
249
+ const taxRate = await tax_rates.retrieve({ sdk: stall, id: 'tax_rate_123' });
250
+ const newTaxRate = await tax_rates.create({ sdk: stall, data: { rate: 0.1 } });
251
+
252
+ // Locations
253
+ const locationList = await locations.list({ sdk: stall, query: 'warehouse' });
254
+ const location = await locations.retrieve({ sdk: stall, id: 'loc_123' });
255
+ const newLocation = await locations.create({ sdk: stall, data: { name: 'Main Warehouse' } });
256
+ ```
257
+
258
+ ### Fulfillment
259
+
260
+ ```typescript
261
+ // Fulfillments
262
+ const fulfillmentList = await fulfillments.list({ sdk: stall, query: 'pending' });
263
+ const fulfillment = await fulfillments.retrieve({ sdk: stall, id: 'ful_123' });
264
+ const newFulfillment = await fulfillments.create({ sdk: stall, data: { order_id: 'order_123' } });
265
+ ```
266
+
267
+ ## Adapter Architecture
268
+
269
+ ### How It Works
270
+
271
+ 1. **Initialization**: `initializeStallCore()` creates a `CoreConfig` object with your connector settings
272
+ 2. **Adapter Loading**: First service call triggers `sdk.adapter()` which:
273
+ - Checks IndexedDB cache for existing adapter module
274
+ - If cache exists and valid (TTL not expired): returns cached module
275
+ - If cache missing or expired: fetches fresh module from connector URL
276
+ - Stores module in IndexedDB with timestamp
277
+ 3. **Module Execution**: Adapter module is imported dynamically and executes the requested operation
278
+ 4. **Caching**: Subsequent calls reuse the cached module (up to 4 hours by default)
279
+
280
+ ### Cache Behavior
281
+
282
+ ```typescript
283
+ // First call - fetches from URL
284
+ const products1 = await products.list({ sdk: stall, query: 'laptop' });
285
+
286
+ // Subsequent calls within TTL - uses cache
287
+ const products2 = await products.list({ sdk: stall, query: 'shoes' });
288
+ const products3 = await products.list({ sdk: stall, query: 'hats' });
289
+
290
+ // Force refresh
291
+ await stall.refreshAdapter(); // Clears cache, fetches fresh module
292
+ ```
293
+
294
+ ## Error Handling
295
+
296
+ All service methods are wrapped in try-catch blocks and propagate errors:
297
+
298
+ ```typescript
299
+ try {
300
+ const product = await products.retrieve({ sdk: stall, id: 'invalid_id' });
301
+ } catch (error) {
302
+ console.error('Failed to retrieve product:', error.message);
303
+ }
304
+ ```
305
+
306
+ ## Type Safety
307
+
308
+ All services use TypeScript types from `@use-stall/types`:
309
+
310
+ ```typescript
311
+ import type {
312
+ UnifiedProductType,
313
+ UnifiedOrderType,
314
+ UnifiedCustomerType,
315
+ UnifiedVariantsType,
316
+ UnifiedInventoryLevelType,
317
+ UnifiedCollectionType,
318
+ UnifiedCategoryType,
319
+ UnifiedPromotion,
320
+ UnifiedOrderNote,
321
+ UnifiedOrderRefundType,
322
+ UnifiedPaymentProviderType,
323
+ UnifiedPaymentCollectionType,
324
+ UnifiedTaxRegionType,
325
+ UnifiedTaxRateType,
326
+ UnifiedLocationType,
327
+ UnifiedFulfillmentType,
328
+ } from '@use-stall/types';
329
+ ```
330
+
331
+ ## Configuration
332
+
333
+ ### StallCoreConfigOptions
334
+
335
+ ```typescript
336
+ interface StallCoreConfigOptions {
337
+ connector_url: string; // URL to fetch adapter module from
338
+ version: string; // SDK/adapter version
339
+ configuration: { // Connector-specific credentials
340
+ endpoint: string;
341
+ token?: string;
342
+ username?: string;
343
+ password?: string;
344
+ api_key?: string;
345
+ [key: string]: any;
346
+ };
347
+ }
348
+ ```
349
+
350
+ ### CoreConfig (Returned from initialization)
351
+
352
+ ```typescript
353
+ interface CoreConfig {
354
+ options: StallCoreConfigOptions;
355
+ adapter: () => Promise<AdapterModuleType>; // Get or fetch adapter
356
+ refreshAdapter: () => Promise<AdapterModuleType>; // Force refresh
357
+ }
358
+ ```
359
+
360
+ ## Best Practices
361
+
362
+ 1. **Initialize once**: Create the SDK instance once and reuse it
363
+
364
+ ```typescript
365
+ const stall = initializeStallCore({ ... });
366
+ // Use stall across your application
367
+ ```
368
+
369
+ 2. **Use the service imports**: Import services from the main package
370
+
371
+ ```typescript
372
+ import { products, orders, customers } from '@use-stall/core';
373
+ ```
374
+
375
+ 3. **Handle errors properly**: Always wrap calls in try-catch
376
+
377
+ ```typescript
378
+ try {
379
+ const result = await products.list({ sdk: stall, query: 'search' });
380
+ } catch (error) {
381
+ // Handle error
382
+ }
383
+ ```
384
+
385
+ 4. **Leverage bulk operations**: For multiple operations, use bulk methods
386
+
387
+ ```typescript
388
+ // Better than multiple create() calls
389
+ const items = await products.bulk_create({
390
+ sdk: stall,
391
+ data: [
392
+ { name: 'Product 1' },
393
+ { name: 'Product 2' },
394
+ { name: 'Product 3' },
395
+ ]
396
+ });
397
+ ```
398
+
399
+ 5. **Type your data**: Use TypeScript types for safety
400
+
401
+ ```typescript
402
+ import type { UnifiedProductType } from '@use-stall/types';
403
+
404
+ const product: UnifiedProductType = {
405
+ id: 'prod_123',
406
+ name: 'My Product',
407
+ // ... other fields
408
+ };
409
+
410
+ await products.create({ sdk: stall, data: product });
411
+ ```
412
+
413
+ ## File Structure
414
+
415
+ ```
416
+ core/src/
417
+ ├── core/
418
+ │ ├── init.ts (Initialization logic)
419
+ │ └── sdk.ts (Main exports + documentation)
420
+ ├── services/ (Service modules - one per entity)
421
+ │ ├── products.service.ts
422
+ │ ├── orders.service.ts
423
+ │ ├── customers.service.ts
424
+ │ ├── collections.service.ts
425
+ │ ├── categories.service.ts
426
+ │ ├── variants.service.ts
427
+ │ ├── inventory-levels.service.ts
428
+ │ ├── promotions.service.ts
429
+ │ ├── order-notes.service.ts
430
+ │ ├── refunds.service.ts
431
+ │ ├── payment-providers.service.ts
432
+ │ ├── payments.service.ts
433
+ │ ├── tax-regions.service.ts
434
+ │ ├── tax-rates.service.ts
435
+ │ ├── locations.service.ts
436
+ │ └── fulfillments.service.ts
437
+ ├── types/
438
+ │ └── core.d.ts (TypeScript definitions)
439
+ ├── db/
440
+ │ ├── db.ts (Dexie database setup)
441
+ │ ├── schema.ts (Database schema)
442
+ │ └── helpers.ts (Database helpers)
443
+ └── index.ts (Main entry point)
444
+ ```
445
+
446
+ ## Service Summary
447
+
448
+ | Service | Purpose | Operations |
449
+ |---------|---------|-----------|
450
+ | `products` | Product management | CRUD + bulk |
451
+ | `variants` | Product variants | CRUD + bulk |
452
+ | `categories` | Product categories | CRUD + bulk |
453
+ | `collections` | Product collections | CRUD + bulk |
454
+ | `inventory_levels` | Inventory tracking | CRUD + bulk |
455
+ | `orders` | Order management | CRUD + bulk |
456
+ | `order_notes` | Order comments/notes | CRUD + bulk |
457
+ | `refunds` | Refund management | CRUD + bulk |
458
+ | `customers` | Customer management | CRUD + bulk |
459
+ | `promotions` | Promotions/discounts | CRUD + bulk |
460
+ | `payment_providers` | Payment providers | CRUD + bulk |
461
+ | `payments` | Payment transactions | CRUD + bulk |
462
+ | `tax_regions` | Tax configuration | CRUD + bulk |
463
+ | `tax_rates` | Tax rates | CRUD + bulk |
464
+ | `locations` | Store locations | CRUD + bulk |
465
+ | `fulfillments` | Order fulfillment | CRUD + bulk |
466
+
467
+ ## Development
468
+
469
+ Built with Bun and TypeScript. The SDK uses:
470
+
471
+ - **Dexie.js** for IndexedDB management
472
+ - **@use-stall/types** for unified type definitions
473
+ - **TypeScript** for type safety
474
+
475
+ ## License
476
+
477
+ MIT