@use-stall/core 0.0.2 → 0.0.4

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 CHANGED
@@ -1,16 +1,17 @@
1
- # Stall Universal Connector SDK
1
+ # Stall Core SDK
2
2
 
3
- A universal, type-safe SDK for integrating multiple commerce connectors (WooCommerce, Shopify, Medusa, etc.) with a unified interface. The SDK enables seamless communication with various data sources while maintaining a consistent API across all connectors.
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
4
 
5
5
  ## Overview
6
6
 
7
- The Stall SDK provides a plugin-based architecture that allows you to:
7
+ The Stall Core SDK provides an adapter-based architecture that allows you to:
8
8
 
9
- - **Load connector plugins** dynamically from a public connector URL
10
- - **Standardize operations** across different commerce platforms
11
- - **Work with unified types** for orders, products, customers, and more
12
- - **Handle authentication** transparently across different auth methods
13
- - **Manage errors** consistently with detailed error codes and messages
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
14
15
 
15
16
  ## Architecture
16
17
 
@@ -19,544 +20,458 @@ The Stall SDK provides a plugin-based architecture that allows you to:
19
20
  │ Your Application │
20
21
  └──────────────┬──────────────────────┘
21
22
 
22
- ┌──────────────▼──────────────────────┐
23
- StallSDK (Main Entry)
24
- - Firebase-style initialization │
25
- │ - Service management │
26
- └──────────────┬──────────────────────┘
27
-
28
- ┌──────┴──────┐
29
- │ │
30
- ┌───────▼─────┐ ┌────▼──────────┐
31
- │ Orders Products │
32
- │ Service Service │
33
- └───────┬─────┘ └────┬──────────┘
34
-
35
- └──────┬──────┘
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
+ └──────────┬──────────┘
36
44
 
37
- ┌─────────▼──────────┐
38
- Plugin Manager
39
- - Lifecycle
40
- │ - Verification
41
- └─────────┬──────────┘
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
+ └──────────┬──────────────────┘
42
57
 
43
- ┌─────────▼──────────┐
44
- Connector Loader
45
- - Public URL
46
- │ - Caching │
47
- └─────────┬──────────┘
58
+ ┌──────────▼──────────────────┐
59
+ Connector Loader
60
+ (Dynamic Module Import)
61
+ └──────────┬──────────────────┘
48
62
 
49
- ┌─────────▼──────────┐
50
- Plugin Instance
51
- │ (WooCommerce, │
52
- Shopify, etc.)
53
- └────────────────────┘
63
+ ┌──────────▼──────────────────┐
64
+ Commerce Platform API
65
+ │ (WooCommerce, Shopify,
66
+ Medusa,Google Sheets etc.)
67
+ └─────────────────────────────┘
54
68
  ```
55
69
 
56
70
  ## Installation
57
71
 
58
- The SDK is part of `@use-stall/core`. Install it with:
59
-
60
72
  ```bash
61
- npm install @use-stall/core
62
- # or
63
73
  bun install @use-stall/core
64
74
  ```
65
75
 
66
76
  ## Quick Start
67
77
 
68
- ### Basic Usage
78
+ ### Initialize the SDK
69
79
 
70
80
  ```typescript
71
- import { StallSDK } from '@use-stall/core';
72
- import { MockConnectorPlugin } from '@use-stall/core';
73
-
74
- // Initialize the SDK with a mock connector for testing
75
- const stall = await StallSDK.initializeWithPlugin(
76
- {
77
- id: 'config_123',
78
- integration_id: 'mock',
79
- created_at: Date.now(),
80
- updated_at: Date.now(),
81
- configuration: {
82
- endpoint: 'https://example.com/api',
83
- },
84
- },
85
- new MockConnectorPlugin()
86
- );
87
-
88
- // Create an order
89
- const orderResult = await stall.orders.createOrder({
90
- id: 'order_123',
91
- order_number: 'ORD-001',
92
- status: 'pending',
93
- total: 99.99,
94
- // ... other order fields
95
- });
96
-
97
- if (orderResult.success) {
98
- console.log('Order created:', orderResult.data);
99
- } else {
100
- console.error('Failed to create order:', orderResult.error);
101
- }
102
- ```
103
-
104
- ### Remote Plugin Loading from Public URL
81
+ import { initializeStallCore, products, orders, customers } from '@use-stall/core';
105
82
 
106
- ```typescript
107
- import { StallSDK } from '@use-stall/core';
108
-
109
- // Initialize with public connector URL
110
- // Default: https://connectors.myapp.xyz/{integration_id}/index.js
111
- const stall = await StallSDK.initialize({
112
- id: 'config_123',
113
- integration_id: 'woocommerce',
114
- created_at: Date.now(),
115
- updated_at: Date.now(),
83
+ // Initialize with connector configuration
84
+ const stall = initializeStallCore({
85
+ connector_url: 'https://connectors.myapp.xyz/woocommerce',
86
+ version: '1.0.0',
116
87
  configuration: {
117
88
  endpoint: 'https://myshop.com',
118
89
  token: process.env.WOOCOMMERCE_TOKEN,
119
90
  },
120
- options: {
121
- logLevel: 'info',
122
- cachePlugins: true,
123
- // connectorUrl is optional, defaults to https://connectors.myapp.xyz
124
- },
125
91
  });
126
-
127
- // Verify connection
128
- const isConnected = await stall.verify();
129
- console.log('Connected:', isConnected);
130
-
131
- // Get metadata
132
- const metadata = stall.getMetadata();
133
- console.log('Connector:', metadata.name, metadata.version);
134
-
135
- // List products
136
- const products = await stall.products.listProducts({ limit: 10 });
137
- if (products.success) {
138
- console.log('Products:', products.data);
139
- }
140
92
  ```
141
93
 
142
- ## Services
143
-
144
- ### Orders Service
94
+ ### Use Any Service
145
95
 
146
96
  ```typescript
147
- // Create an order
148
- const result = await stall.orders.createOrder(unifiedOrder);
149
-
150
- // Get an order
151
- const result = await stall.orders.getOrder('order_id');
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
+ ```
152
129
 
153
- // Update an order
154
- const result = await stall.orders.updateOrder('order_id', { status: 'completed' });
130
+ ## Available Services
155
131
 
156
- // Delete/cancel an order
157
- const result = await stall.orders.deleteOrder('order_id');
132
+ ### Core CRUD Operations
158
133
 
159
- // List orders
160
- const result = await stall.orders.listOrders({ limit: 20, offset: 0 });
134
+ Each service module provides 8 standard operations:
161
135
 
162
- // Create a refund
163
- const result = await stall.orders.createRefund('order_id', refundData);
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
164
144
 
165
- // Get a refund
166
- const result = await stall.orders.getRefund('refund_id');
145
+ ### Inventory & Catalog
167
146
 
168
- // List refunds
169
- const result = await stall.orders.listRefunds('order_id');
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'] });
170
180
  ```
171
181
 
172
- ### Products Service
182
+ ### Order Management
173
183
 
174
184
  ```typescript
175
- // Create a product
176
- const result = await stall.products.createProduct(unifiedProduct);
177
-
178
- // Get a product
179
- const result = await stall.products.getProduct('product_id');
180
-
181
- // Update a product
182
- const result = await stall.products.updateProduct('product_id', { price: 199.99 });
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
+ ```
183
202
 
184
- // Delete a product
185
- const result = await stall.products.deleteProduct('product_id');
203
+ ### Customer Management
186
204
 
187
- // List products
188
- const result = await stall.products.listProducts({
189
- limit: 50,
190
- category: 'electronics'
191
- });
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' });
192
212
  ```
193
213
 
194
- ## Types
214
+ ### Promotions
195
215
 
196
- ### Unified Types
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
+ ```
197
222
 
198
- The SDK uses unified types from `@use-stall/types`:
223
+ ### Payment Management
199
224
 
200
225
  ```typescript
201
- import type {
202
- UnifiedOrderType,
203
- UnifiedProductType,
204
- UnifiedOrderRefundType,
205
- ConnectorConfigurationType,
206
- } from '@use-stall/core';
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 } });
207
237
  ```
208
238
 
209
- ### Response Format
210
-
211
- All operations return a standardized response:
239
+ ### Tax & Location
212
240
 
213
241
  ```typescript
214
- interface ConnectorResponse<T> {
215
- success: boolean;
216
- data?: T;
217
- error?: {
218
- code: string;
219
- message: string;
220
- details?: Record<string, any>;
221
- };
222
- metadata?: {
223
- timestamp: number;
224
- connector_id: string;
225
- operation: string;
226
- request_id: string;
227
- };
228
- }
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' } });
229
256
  ```
230
257
 
231
- ## Error Handling
232
-
233
- The SDK provides comprehensive error handling with specific error codes:
258
+ ### Fulfillment
234
259
 
235
260
  ```typescript
236
- import { StallConnectorError, ErrorCodes } from '@use-stall/core';
237
-
238
- try {
239
- const result = await stall.orders.createOrder(order);
240
- if (!result.success) {
241
- switch (result.error?.code) {
242
- case ErrorCodes.INVALID_CREDENTIALS:
243
- console.error('Invalid connector credentials');
244
- break;
245
- case ErrorCodes.RATE_LIMITED:
246
- console.error('Rate limit exceeded');
247
- break;
248
- case ErrorCodes.OPERATION_TIMEOUT:
249
- console.error('Operation timed out');
250
- break;
251
- default:
252
- console.error('Operation failed:', result.error?.message);
253
- }
254
- }
255
- } catch (error) {
256
- if (error instanceof StallConnectorError) {
257
- console.error('Connector error:', error.code, error.message);
258
- }
259
- }
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' } });
260
265
  ```
261
266
 
262
- ### Error Codes
267
+ ## Adapter Architecture
263
268
 
264
- - **Configuration Errors**: `INVALID_CONFIGURATION`, `MISSING_CREDENTIALS`, `INVALID_CREDENTIALS`
265
- - **Plugin Errors**: `PLUGIN_LOAD_FAILED`, `PLUGIN_NOT_FOUND`
266
- - **Operation Errors**: `OPERATION_FAILED`, `OPERATION_TIMEOUT`, `OPERATION_NOT_SUPPORTED`
267
- - **Network Errors**: `NETWORK_ERROR`, `REQUEST_FAILED`, `RATE_LIMITED`
268
- - **Validation Errors**: `VALIDATION_FAILED`, `INVALID_DATA`, `MISSING_REQUIRED_FIELD`
269
- - **Auth Errors**: `UNAUTHORIZED`, `FORBIDDEN`, `TOKEN_EXPIRED`
270
- - **Server Errors**: `INTERNAL_ERROR`, `SERVICE_UNAVAILABLE`
269
+ ### How It Works
271
270
 
272
- ## Creating Custom Connector Plugins
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)
273
279
 
274
- Connector plugins implement the `IConnectorPlugin` interface:
280
+ ### Cache Behavior
275
281
 
276
282
  ```typescript
277
- import type { IConnectorPlugin, ConnectorResponse, ConnectorPluginConfig } from '@use-stall/core';
278
- import type { UnifiedOrderType, UnifiedProductType } from '@use-stall/types';
279
-
280
- export class MyConnectorPlugin implements IConnectorPlugin {
281
- metadata = {
282
- id: 'my-connector',
283
- name: 'My Connector',
284
- version: '1.0.0',
285
- description: 'My custom connector',
286
- };
287
-
288
- async initialize(config: ConnectorPluginConfig): Promise<void> {
289
- // Initialize your connector with the provided configuration
290
- this.endpoint = config.configuration.endpoint;
291
- this.token = config.configuration.token;
292
- }
293
-
294
- async verify(): Promise<ConnectorResponse<boolean>> {
295
- // Verify the connector can connect to the external service
296
- try {
297
- await this.makeRequest('GET', '/status');
298
- return { success: true, data: true };
299
- } catch (error) {
300
- return {
301
- success: false,
302
- error: { code: 'CONNECTION_FAILED', message: error.message },
303
- };
304
- }
305
- }
306
-
307
- getSupportedModules(): string[] {
308
- return ['orders', 'products', 'customers', 'inventory'];
309
- }
310
-
311
- orders = {
312
- create: async (order: UnifiedOrderType): Promise<ConnectorResponse<any>> => {
313
- // Map from unified format to connector-specific format
314
- const connectorOrder = this.mapOrderToConnectorFormat(order);
315
-
316
- try {
317
- const response = await this.makeRequest('POST', '/orders', connectorOrder);
318
- return {
319
- success: true,
320
- data: this.mapOrderToUnifiedFormat(response),
321
- };
322
- } catch (error) {
323
- return {
324
- success: false,
325
- error: { code: 'CREATE_FAILED', message: error.message },
326
- };
327
- }
328
- },
329
-
330
- get: async (orderId: string): Promise<ConnectorResponse<any>> => {
331
- // Implementation
332
- },
333
-
334
- update: async (orderId: string, order: Partial<UnifiedOrderType>) => {
335
- // Implementation
336
- },
337
-
338
- delete: async (orderId: string) => {
339
- // Implementation
340
- },
341
-
342
- list: async (options?: any) => {
343
- // Implementation
344
- },
345
- };
283
+ // First call - fetches from URL
284
+ const products1 = await products.list({ sdk: stall, query: 'laptop' });
346
285
 
347
- products = {
348
- // Similar implementation for products
349
- };
350
-
351
- customers = {
352
- // Similar implementation for customers
353
- };
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' });
354
289
 
355
- inventory = {
356
- // Similar implementation for inventory
357
- };
358
-
359
- refunds = {
360
- // Similar implementation for refunds
361
- };
362
-
363
- payments = {
364
- // Similar implementation for payments
365
- };
366
- }
290
+ // Force refresh
291
+ await stall.refreshAdapter(); // Clears cache, fetches fresh module
367
292
  ```
368
293
 
369
- ## Logging
294
+ ## Error Handling
370
295
 
371
- The SDK includes built-in logging. Control the log level during initialization:
296
+ All service methods are wrapped in try-catch blocks and propagate errors:
372
297
 
373
298
  ```typescript
374
- const stall = await StallSDK.initialize({
375
- // ... config
376
- options: {
377
- logLevel: 'debug', // 'debug' | 'info' | 'warn' | 'error'
378
- },
379
- });
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
+ }
380
304
  ```
381
305
 
382
- You can also use the logger directly:
306
+ ## Type Safety
383
307
 
384
- ```typescript
385
- import { createLogger } from '@use-stall/core';
308
+ All services use TypeScript types from `@use-stall/types`:
386
309
 
387
- const logger = createLogger('MyApp', 'info');
388
- logger.info('Application started');
389
- logger.debug('Debug information');
390
- logger.warn('Warning message');
391
- logger.error('Error occurred', error);
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';
392
329
  ```
393
330
 
394
331
  ## Configuration
395
332
 
396
- ### ConnectorConfigurationType
333
+ ### StallCoreConfigOptions
397
334
 
398
335
  ```typescript
399
- interface ConnectorConfigurationType {
400
- id: string;
401
- integration_id: string;
402
- created_at: number;
403
- updated_at: number;
404
- configuration: {
336
+ interface StallCoreConfigOptions {
337
+ connector_url: string; // URL to fetch adapter module from
338
+ version: string; // SDK/adapter version
339
+ configuration: { // Connector-specific credentials
405
340
  endpoint: string;
341
+ token?: string;
406
342
  username?: string;
407
343
  password?: string;
408
- token?: string;
409
- api_key_header?: string;
410
- api_key_value?: string;
344
+ api_key?: string;
411
345
  [key: string]: any;
412
346
  };
413
347
  }
414
348
  ```
415
349
 
416
- ### StallSDKOptions
417
-
418
- Extends `ConnectorConfigurationType` from `@use-stall/types`:
350
+ ### CoreConfig (Returned from initialization)
419
351
 
420
352
  ```typescript
421
- interface StallSDKOptions extends ConnectorConfigurationType {
422
- // Inherits: id, integration_id, created_at, updated_at, configuration
423
-
424
- options?: {
425
- timeout?: number;
426
- retries?: number;
427
- logLevel?: 'debug' | 'info' | 'warn' | 'error';
428
- cachePlugins?: boolean;
429
- connectorUrl?: string; // Base URL for public connector plugins
430
- // Default: https://connectors.myapp.xyz
431
- };
432
- }
433
- ```
434
-
435
- ### ConnectorConfigurationType
436
-
437
- ```typescript
438
- interface ConnectorConfigurationType {
439
- id: string; // Configuration ID
440
- integration_id: string; // Integration type (woocommerce, shopify, etc.)
441
- created_at: number; // Timestamp
442
- updated_at: number; // Timestamp
443
- configuration: {
444
- endpoint: string; // Platform API endpoint
445
- username?: string; // Basic auth username
446
- password?: string; // Basic auth password
447
- token?: string; // Bearer token
448
- api_key_header?: string; // API key header name
449
- api_key_value?: string; // API key value
450
- [key: string]: any; // Custom fields
451
- };
353
+ interface CoreConfig {
354
+ options: StallCoreConfigOptions;
355
+ adapter: () => Promise<AdapterModuleType>; // Get or fetch adapter
356
+ refreshAdapter: () => Promise<AdapterModuleType>; // Force refresh
452
357
  }
453
358
  ```
454
359
 
455
360
  ## Best Practices
456
361
 
457
- 1. **Always check the response**: Every SDK operation returns a `ConnectorResponse` that includes a `success` flag.
362
+ 1. **Initialize once**: Create the SDK instance once and reuse it
458
363
 
459
364
  ```typescript
460
- const result = await stall.orders.createOrder(order);
461
- if (result.success) {
462
- // Handle success
463
- } else {
464
- // Handle error
465
- console.error(result.error?.code, result.error?.message);
466
- }
365
+ const stall = initializeStallCore({ ... });
366
+ // Use stall across your application
467
367
  ```
468
368
 
469
- 2. **Use TypeScript types**: Leverage the unified types to ensure type safety.
369
+ 2. **Use the service imports**: Import services from the main package
470
370
 
471
371
  ```typescript
472
- import type { UnifiedOrderType } from '@use-stall/core';
473
-
474
- const order: UnifiedOrderType = {
475
- id: 'order_123',
476
- // ... other required fields
477
- };
372
+ import { products, orders, customers } from '@use-stall/core';
478
373
  ```
479
374
 
480
- 3. **Handle module support checking**: Not all connectors support all modules.
375
+ 3. **Handle errors properly**: Always wrap calls in try-catch
481
376
 
482
377
  ```typescript
483
- if (stall.isModuleSupported('inventory')) {
484
- // Safe to use inventory operations
378
+ try {
379
+ const result = await products.list({ sdk: stall, query: 'search' });
380
+ } catch (error) {
381
+ // Handle error
485
382
  }
486
383
  ```
487
384
 
488
- 4. **Verify connection on startup**: Always verify the connector is properly configured.
385
+ 4. **Leverage bulk operations**: For multiple operations, use bulk methods
489
386
 
490
387
  ```typescript
491
- const isConnected = await stall.verify();
492
- if (!isConnected) {
493
- throw new Error('Failed to connect to connector');
494
- }
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
+ });
495
397
  ```
496
398
 
497
- 5. **Cache plugins when appropriate**: For better performance, enable plugin caching.
399
+ 5. **Type your data**: Use TypeScript types for safety
498
400
 
499
401
  ```typescript
500
- options: {
501
- cachePlugins: true, // Default: true
502
- }
503
- ```
402
+ import type { UnifiedProductType } from '@use-stall/types';
504
403
 
505
- ## Development with Mock Plugin
506
-
507
- For local development and testing, use the `MockConnectorPlugin`:
404
+ const product: UnifiedProductType = {
405
+ id: 'prod_123',
406
+ name: 'My Product',
407
+ // ... other fields
408
+ };
508
409
 
509
- ```typescript
510
- import { MockConnectorPlugin, StallSDK } from '@use-stall/core';
511
-
512
- const mockStall = await StallSDK.initializeWithPlugin(
513
- {
514
- id: 'config_test',
515
- integration_id: 'mock',
516
- created_at: Date.now(),
517
- updated_at: Date.now(),
518
- configuration: { /* ... */ },
519
- },
520
- new MockConnectorPlugin()
521
- );
410
+ await products.create({ sdk: stall, data: product });
522
411
  ```
523
412
 
524
- ## Environment Variables
525
-
526
- Recommended environment variables for production:
527
-
528
- ```bash
529
- # Connector URL (optional, defaults to https://connectors.myapp.xyz)
530
- CONNECTOR_URL=https://connectors.myapp.xyz
413
+ ## File Structure
531
414
 
532
- # Connector-specific credentials (these go in the configuration object)
533
- WOOCOMMERCE_TOKEN=your_token
534
- SHOPIFY_TOKEN=your_token
535
- MEDUSA_API_KEY=your_api_key
536
415
  ```
537
-
538
- Example usage:
539
-
540
- ```typescript
541
- const stall = await StallSDK.initialize({
542
- id: 'config_123',
543
- integration_id: 'woocommerce',
544
- created_at: Date.now(),
545
- updated_at: Date.now(),
546
- configuration: {
547
- endpoint: 'https://myshop.com',
548
- token: process.env.WOOCOMMERCE_TOKEN,
549
- },
550
- options: {
551
- connectorUrl: process.env.CONNECTOR_URL || 'https://connectors.myapp.xyz',
552
- },
553
- });
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)
554
444
  ```
555
445
 
556
- ## License
557
-
558
- MIT
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
559
474
 
560
- ## Support
475
+ ## License
561
476
 
562
- For issues, questions, or contributions, please visit the Stall GitHub repository.
477
+ MIT