@commercengine/pos 0.1.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/README.md ADDED
@@ -0,0 +1,552 @@
1
+ # @commercengine/pos
2
+
3
+ TypeScript SDK for the Commerce Engine Point of Sale (POS) API. This package provides a complete interface to manage POS operations including authentication, cart management, orders, promotions, and customer interactions.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @commercengine/pos
9
+ # or
10
+ yarn add @commercengine/pos
11
+ # or
12
+ pnpm add @commercengine/pos
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { PosSDK } from '@commercengine/pos';
19
+
20
+ // Initialize the SDK
21
+ const pos = new PosSDK({
22
+ storeId: 'your-store-id',
23
+ apiKey: 'your-api-key',
24
+ });
25
+
26
+ // Login with email (returns OTP token)
27
+ const { data: loginData, error: loginError } = await pos.pos.loginWithEmail({
28
+ device_id: 'device-123',
29
+ email: 'cashier@store.com'
30
+ });
31
+
32
+ if (loginError) {
33
+ console.error('Login failed:', loginError);
34
+ return;
35
+ }
36
+
37
+ // Verify OTP to get access tokens
38
+ const { data: authData, error: authError } = await pos.pos.verifyOtp({
39
+ otp_token: loginData.otp_token,
40
+ otp: '123456'
41
+ });
42
+
43
+ if (authError) {
44
+ console.error('OTP verification failed:', authError);
45
+ return;
46
+ }
47
+
48
+ // Now you can make authenticated requests
49
+ const { data: cartData, error: cartError } = await pos.pos.createCart({
50
+ currency: 'USD'
51
+ });
52
+
53
+ if (cartData) {
54
+ console.log('Cart created:', cartData);
55
+ }
56
+ ```
57
+
58
+ ## Configuration Options
59
+
60
+ The `PosSDK` constructor accepts a `PosSDKOptions` object with the following configuration:
61
+
62
+ ### Required Options
63
+
64
+ | Option | Type | Description |
65
+ |--------|------|-------------|
66
+ | `storeId` | `string` | Your Commerce Engine store ID |
67
+ | `apiKey` | `string` | API key for authentication endpoints (required for all POS operations) |
68
+
69
+ ### Optional Options
70
+
71
+ | Option | Type | Description |
72
+ |--------|------|-------------|
73
+ | `environment` | `Environment` | API environment (`Environment.Production`, `Environment.Staging`, `Environment.Development`) |
74
+ | `baseUrl` | `string` | Custom base URL (overrides environment setting) |
75
+ | `accessToken` | `string` | Initial access token (if you already have one) |
76
+ | `refreshToken` | `string` | Initial refresh token (requires `tokenStorage`) |
77
+ | `tokenStorage` | `TokenStorage` | Automatic token management (recommended) |
78
+ | `onTokensUpdated` | `function` | Callback when tokens are refreshed |
79
+ | `onTokensCleared` | `function` | Callback when tokens are cleared/expired |
80
+ | `timeout` | `number` | Request timeout in milliseconds |
81
+ | `defaultHeaders` | `SupportedDefaultHeaders` | Default headers for all requests |
82
+ | `debug` | `boolean` | Enable debug logging |
83
+ | `logger` | `DebugLoggerFn` | Custom debug logger function |
84
+
85
+ ### BaseSDKOptions (inherited from @commercengine/sdk-core)
86
+
87
+ The POS SDK extends the base SDK configuration with these inherited options:
88
+
89
+ - **baseUrl**: Custom API base URL
90
+ - **timeout**: Request timeout (default: 30000ms)
91
+ - **defaultHeaders**: Default headers applied to all requests
92
+ - **debug**: Enable request/response logging
93
+ - **logger**: Custom logger function for debug output
94
+
95
+ ### Advanced Configuration
96
+
97
+ ```typescript
98
+ const pos = new PosSDK({
99
+ storeId: 'your-store-id',
100
+ apiKey: 'your-api-key',
101
+ environment: Environment.Production,
102
+
103
+ // Token Management
104
+ accessToken: 'initial-access-token', // Initial access token
105
+ refreshToken: 'initial-refresh-token', // Initial refresh token (requires tokenStorage)
106
+
107
+ // Custom base URL (optional, overrides environment)
108
+ baseUrl: 'https://your-custom-api.example.com',
109
+
110
+ // Request Configuration
111
+ timeout: 10000, // Request timeout in milliseconds
112
+
113
+ // Default Headers (auto applied to all applicable requests)
114
+ defaultHeaders: {
115
+ customer_group_id: '01JHS28V83KDWTRBXXJQRTEKA0', // For pricing and promotions
116
+ },
117
+
118
+ // Debug and Logging
119
+ debug: true, // Enable detailed request/response logging
120
+ logger: console.log, // Custom logger function
121
+ });
122
+ ```
123
+
124
+ ### Supported Default Headers
125
+
126
+ ```typescript
127
+ interface SupportedDefaultHeaders {
128
+ /**
129
+ * Customer group ID used for pricing and promotions
130
+ */
131
+ customer_group_id?: string;
132
+ }
133
+ ```
134
+
135
+ ## Token Management
136
+
137
+ The POS SDK supports three token management strategies:
138
+
139
+ ### 1. Automatic Token Management (Recommended)
140
+
141
+ ```typescript
142
+ import { PosSDK, BrowserTokenStorage } from '@commercengine/pos';
143
+
144
+ const pos = new PosSDK({
145
+ storeId: 'your-store-id',
146
+ apiKey: 'your-api-key',
147
+ tokenStorage: new BrowserTokenStorage(), // or new MemoryTokenStorage()
148
+ onTokensUpdated: (accessToken, refreshToken) => {
149
+ console.log('Tokens updated');
150
+ },
151
+ onTokensCleared: () => {
152
+ console.log('User logged out');
153
+ }
154
+ });
155
+ ```
156
+
157
+ ### 2. Manual Token Management
158
+
159
+ ```typescript
160
+ const pos = new PosSDK({
161
+ storeId: 'your-store-id',
162
+ apiKey: 'your-api-key',
163
+ accessToken: 'existing-access-token'
164
+ });
165
+
166
+ // Update tokens manually
167
+ await pos.setTokens('new-access-token', 'new-refresh-token');
168
+ ```
169
+
170
+ ### 3. Initialize with Existing Tokens
171
+
172
+ ```typescript
173
+ const pos = new PosSDK({
174
+ storeId: 'your-store-id',
175
+ apiKey: 'your-api-key',
176
+ accessToken: 'existing-access-token',
177
+ refreshToken: 'existing-refresh-token',
178
+ tokenStorage: new BrowserTokenStorage() // Enables automatic refresh
179
+ });
180
+ ```
181
+
182
+ ## Token Storage Options
183
+
184
+ ### BrowserTokenStorage
185
+ Stores tokens in `localStorage` with customizable prefix:
186
+
187
+ ```typescript
188
+ import { BrowserTokenStorage } from '@commercengine/pos';
189
+
190
+ const storage = new BrowserTokenStorage('my_pos_'); // prefix: default 'pos_'
191
+ ```
192
+
193
+ ### MemoryTokenStorage
194
+ Stores tokens in memory (lost on page refresh):
195
+
196
+ ```typescript
197
+ import { MemoryTokenStorage } from '@commercengine/pos';
198
+
199
+ const storage = new MemoryTokenStorage();
200
+ ```
201
+
202
+ ### Custom TokenStorage
203
+ Implement the `TokenStorage` interface for custom storage:
204
+
205
+ ```typescript
206
+ import { TokenStorage } from '@commercengine/pos';
207
+
208
+ class CustomTokenStorage implements TokenStorage {
209
+ async getAccessToken(): Promise<string | null> { /* ... */ }
210
+ async setAccessToken(token: string): Promise<void> { /* ... */ }
211
+ async getRefreshToken(): Promise<string | null> { /* ... */ }
212
+ async setRefreshToken(token: string): Promise<void> { /* ... */ }
213
+ async clearTokens(): Promise<void> { /* ... */ }
214
+ }
215
+ ```
216
+
217
+ ## Authentication Flow
218
+
219
+ The POS SDK uses a two-step authentication process:
220
+
221
+ ### Step 1: Login (Request OTP)
222
+
223
+ ```typescript
224
+ // Login with email
225
+ const { data: emailData, error: emailError } = await pos.pos.loginWithEmail({
226
+ device_id: 'unique-device-id',
227
+ email: 'user@example.com'
228
+ });
229
+
230
+ if (emailError) {
231
+ console.error('Email login failed:', emailError);
232
+ return;
233
+ }
234
+
235
+ // Login with phone
236
+ const { data: phoneData, error: phoneError } = await pos.pos.loginWithPhone({
237
+ device_id: 'unique-device-id',
238
+ phone: '+1234567890'
239
+ });
240
+
241
+ // Login with WhatsApp
242
+ const { data: whatsappData, error: whatsappError } = await pos.pos.loginWithWhatsapp({
243
+ device_id: 'unique-device-id',
244
+ phone: '+1234567890'
245
+ });
246
+ ```
247
+
248
+ ### Step 2: Verify OTP
249
+
250
+ ```typescript
251
+ const { data: authData, error: authError } = await pos.pos.verifyOtp({
252
+ otp_token: emailData.otp_token,
253
+ otp: '123456'
254
+ });
255
+
256
+ if (authError) {
257
+ console.error('OTP verification failed:', authError);
258
+ return;
259
+ }
260
+
261
+ // Access token and refresh token are now automatically stored
262
+ // if tokenStorage is configured
263
+ console.log('Authentication successful:', authData);
264
+ ```
265
+
266
+ ### Device Pairing
267
+
268
+ For new devices, you may need to pair first:
269
+
270
+ ```typescript
271
+ const { data: pairData, error: pairError } = await pos.pos.pairDevice({
272
+ pairing_code: 'ABC123'
273
+ });
274
+
275
+ if (pairError) {
276
+ console.error('Device pairing failed:', pairError);
277
+ return;
278
+ }
279
+
280
+ console.log('Device paired successfully:', pairData);
281
+ ```
282
+
283
+ ## API Operations
284
+
285
+ The POS SDK provides access to all POS operations through the `pos` property:
286
+
287
+ ### Authentication
288
+ - `loginWithEmail()` - Login with email address
289
+ - `loginWithPhone()` - Login with phone number
290
+ - `loginWithWhatsapp()` - Login with WhatsApp
291
+ - `pairDevice()` - Pair a new device
292
+ - `verifyOtp()` - Verify OTP and get tokens
293
+ - `refreshToken()` - Refresh access token
294
+
295
+ ### Cart Management
296
+ - `createCart()` - Create a new cart
297
+ - `getCart()` - Get cart details
298
+ - `updateCart()` - Update cart information
299
+ - `deleteCart()` - Delete cart
300
+
301
+ ### Cart Items (coming soon)
302
+ - Add/remove/update line items
303
+ - Apply discounts and promotions
304
+
305
+ ### Orders
306
+ - `createOrder()` - Create order from cart
307
+
308
+ ### Promotions & Coupons
309
+ - `listPromotions()` - Get available promotions
310
+ - `evaluatePromotions()` - Calculate promotion discounts
311
+ - `listCoupons()` - Get available coupons
312
+ - `applyCoupon()` - Apply coupon to cart
313
+ - `removeCoupon()` - Remove coupon from cart
314
+
315
+ ### Gift Cards & Loyalty
316
+ - `redeemGiftCard()` - Apply gift card to cart
317
+ - `removeGiftCard()` - Remove gift card from cart
318
+ - `redeemLoyaltyPoints()` - Apply loyalty points
319
+ - `removeLoyaltyPoints()` - Remove loyalty points
320
+
321
+ ### Fulfillment
322
+ - `updateFulfillmentPreference()` - Set pickup/delivery options
323
+ - `getFulfillmentOptions()` - Get available fulfillment methods
324
+
325
+ ## User Information
326
+
327
+ Access user information from JWT tokens:
328
+
329
+ ```typescript
330
+ // Get complete user information
331
+ const userInfo = await pos.getUserInfo();
332
+ console.log(userInfo?.email, userInfo?.device, userInfo?.location);
333
+
334
+ // Get specific information
335
+ const userId = await pos.getUserId();
336
+ const deviceId = await pos.getDeviceId();
337
+ const locationId = await pos.getLocationId();
338
+ const role = await pos.getRole();
339
+
340
+ // Check authentication status
341
+ const isLoggedIn = await pos.isLoggedIn();
342
+ const isAuthenticated = await pos.isAuthenticated();
343
+ ```
344
+
345
+ ## Error Handling
346
+
347
+ The SDK returns `ApiResult<T>` objects with consistent error handling:
348
+
349
+ ```typescript
350
+ const { data, error, response } = await pos.pos.createCart({ currency: 'USD' });
351
+
352
+ if (error) {
353
+ console.error('Error:', error.message);
354
+ console.error('HTTP Status:', response?.status);
355
+ } else {
356
+ console.log('Cart created:', data);
357
+ }
358
+
359
+ // Alternative pattern - checking for data
360
+ if (data) {
361
+ console.log('Cart created:', data);
362
+ } else {
363
+ console.error('Failed to create cart:', error);
364
+ }
365
+ ```
366
+
367
+ ## Environment Configuration
368
+
369
+ ### Production (Default)
370
+ ```typescript
371
+ const pos = new PosSDK({
372
+ storeId: 'your-store-id',
373
+ apiKey: 'your-api-key',
374
+ // Uses production environment by default
375
+ });
376
+ ```
377
+
378
+ ### Staging
379
+ ```typescript
380
+ import { PosSDK, Environment } from '@commercengine/pos';
381
+
382
+ const pos = new PosSDK({
383
+ storeId: 'your-store-id',
384
+ apiKey: 'your-api-key',
385
+ environment: Environment.Staging
386
+ });
387
+ ```
388
+
389
+ ### Custom Base URL
390
+ ```typescript
391
+ const pos = new PosSDK({
392
+ storeId: 'your-store-id',
393
+ apiKey: 'your-api-key',
394
+ baseUrl: 'https://custom-api.yourstore.com/api/v1/your-store-id/storefront'
395
+ });
396
+ ```
397
+
398
+ ## Debug Mode
399
+
400
+ Enable debug logging to troubleshoot API requests:
401
+
402
+ ```typescript
403
+ const pos = new PosSDK({
404
+ storeId: 'your-store-id',
405
+ apiKey: 'your-api-key',
406
+ debug: true,
407
+ logger: (message, data) => {
408
+ console.log(`[POS SDK] ${message}`, data);
409
+ }
410
+ });
411
+ ```
412
+
413
+ ## TypeScript Support
414
+
415
+ The SDK is written in TypeScript and provides full type safety:
416
+
417
+ ```typescript
418
+ import type {
419
+ PosCreateCartBody,
420
+ PosCreateCartContent,
421
+ UserInfo,
422
+ TokenStorage
423
+ } from '@commercengine/pos';
424
+
425
+ // All API methods are fully typed
426
+ const cart: ApiResult<PosCreateCartContent> = await pos.pos.createCart({
427
+ currency: 'USD' // TypeScript validates this structure
428
+ });
429
+ ```
430
+
431
+ ## Best Practices
432
+
433
+ ### 1. Always Use Token Storage
434
+ Enable automatic token management to handle expiry and refresh:
435
+
436
+ ```typescript
437
+ const pos = new PosSDK({
438
+ storeId: 'your-store-id',
439
+ apiKey: 'your-api-key',
440
+ tokenStorage: new BrowserTokenStorage()
441
+ });
442
+ ```
443
+
444
+ ### 2. Handle Token Events
445
+ Listen for token events to update your application state:
446
+
447
+ ```typescript
448
+ const pos = new PosSDK({
449
+ storeId: 'your-store-id',
450
+ apiKey: 'your-api-key',
451
+ tokenStorage: new BrowserTokenStorage(),
452
+ onTokensUpdated: (accessToken, refreshToken) => {
453
+ // User successfully authenticated or tokens refreshed
454
+ updateUIForLoggedInState();
455
+ },
456
+ onTokensCleared: () => {
457
+ // Tokens expired or user logged out
458
+ redirectToLogin();
459
+ }
460
+ });
461
+ ```
462
+
463
+ ### 3. Error Handling Pattern
464
+ Always check for error before accessing data:
465
+
466
+ ```typescript
467
+ const { data, error, response } = await pos.pos.getCart({ cart_id: 'cart-123' });
468
+
469
+ if (error) {
470
+ if (response?.status === 404) {
471
+ // Cart not found
472
+ showMessage('Cart not found');
473
+ } else {
474
+ // Other error
475
+ showErrorMessage(error.message);
476
+ }
477
+ } else {
478
+ displayCart(data);
479
+ }
480
+ ```
481
+
482
+ ### 4. Use Device IDs Consistently
483
+ Keep device IDs consistent across sessions:
484
+
485
+ ```typescript
486
+ // Store device ID in localStorage
487
+ const deviceId = localStorage.getItem('pos_device_id') || generateDeviceId();
488
+ localStorage.setItem('pos_device_id', deviceId);
489
+
490
+ // Use in all authentication calls
491
+ await pos.pos.loginWithEmail({
492
+ device_id: deviceId,
493
+ email: 'user@example.com'
494
+ });
495
+ ```
496
+
497
+ ## Migration from Other SDKs
498
+
499
+ If you're migrating from the storefront SDK:
500
+
501
+ ### Key Differences
502
+ - **API Key Required**: POS SDK requires `apiKey` for all operations
503
+ - **Two-Step Auth**: Login returns OTP token, must verify with `verifyOtp()`
504
+ - **Device Context**: All operations are scoped to a specific device and location
505
+ - **No Anonymous Mode**: POS SDK requires explicit authentication
506
+
507
+ ### Updated Initialization
508
+ ```typescript
509
+ // Old (storefront)
510
+ const storefront = new StorefrontSDK({
511
+ storeId: 'your-store-id'
512
+ // apiKey was optional
513
+ });
514
+
515
+ // New (POS)
516
+ const pos = new PosSDK({
517
+ storeId: 'your-store-id',
518
+ apiKey: 'your-api-key' // Now required
519
+ });
520
+ ```
521
+
522
+ ## Package Information
523
+
524
+ - **Version**: 0.0.0 (pre-release)
525
+ - **License**: All rights reserved
526
+ - **Dependencies**:
527
+ - `@commercengine/sdk-core` - Core SDK functionality
528
+ - `jose` - JWT token handling
529
+ - `openapi-fetch` - Type-safe API client
530
+
531
+ ## Development
532
+
533
+ ### Generate Types
534
+ Types are auto-generated from the OpenAPI specification:
535
+
536
+ ```bash
537
+ pnpm run codegen
538
+ ```
539
+
540
+ ### Build
541
+ ```bash
542
+ pnpm run build
543
+ ```
544
+
545
+ ### Type Checking
546
+ ```bash
547
+ pnpm run check-exports
548
+ ```
549
+
550
+ ## Support
551
+
552
+ For issues, questions, or feature requests, please contact the Commerce Engine team or check the main repository documentation.