lightspeed-retail-sdk 3.1.2 → 3.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/README.md CHANGED
@@ -1,35 +1,431 @@
1
1
  # Another Unofficial Lightspeed Retail V3 API SDK
2
2
 
3
- A JavaScript SDK for interacting with the Lightspeed Retail API. This SDK provides a convenient way to access Lightspeed Retail's functionalities, including customer, item, order management, and more.
3
+ A modern JavaScript SDK for interacting with the Lightspeed Retail API. This SDK provides a convenient, secure, and flexible way to access Lightspeed Retail's features—including customer, item, and order management.
4
4
 
5
- **Current Version: 3.1.1** - Updated with secure encrypted token storage using Node.js crypto.
5
+ **Current Version: 3.2.0** Now with secure encrypted token storage using Node.js crypto. Useful CLI tools, database tools & email warnings on auth failure.
6
+
7
+ ## **🆕 Recent Updates (v3.2.0)**
8
+
9
+ - **🎯 Enhanced Parameter Support**: All main getter methods now support both legacy and new object-based parameters with full backward compatibility
10
+ - **🔄 Flexible Method Signatures**: New object-based parameters support `{ relations, limit, timeStamp, sort }` for all collection methods
11
+ - **⚡ Improved Performance**: Smart pagination with single-page requests when `limit` is specified
12
+ - **🕒 Timestamp Filtering**: Filter records by modification time using ISO timestamp format
13
+ - **📊 Better Sorting**: Sort results by any field using the `sort` parameter
14
+ - **🔒 Enhanced Error Handling**: All GET methods now return consistent types, never `undefined`
15
+ - **🛠️ Robust API Error Recovery**: Graceful handling of bad requests and empty responses
16
+ - **🐛 Better Debugging**: Enhanced error logging with URLs, status codes, and response data
17
+ - **🔐 Type Safety**: Guaranteed array returns for all list methods
18
+ - **📈 Method Coverage**: Updated 20+ methods with new parameter support including getItems, getCustomers, getSales, getOrders, and more
19
+
20
+ ## 🚀 Key Features
21
+
22
+ - **Modern API**: Object-based parameters with full backward compatibility
23
+ - **Timestamp Filtering**: Get only records updated since a specific time
24
+ - **Robust Error Handling**: Clean, silent error handling with consistent return types
25
+ - **Enhanced CLI**: Browser selection, default scopes, and improved authentication
26
+ - **Multiple Storage Options**: File, encrypted, database, and in-memory token storage
27
+ - **Comprehensive Coverage**: 20+ API methods with consistent interfaces
28
+
29
+ ## 🔄 Migrating from 3.1.x
30
+
31
+ ### Backward Compatibility
32
+
33
+ All existing code continues to work unchanged. **No breaking changes in 3.2.0**.
34
+
35
+ ### New Features Available
36
+
37
+ ```javascript
38
+ // Old way (still works)
39
+ const items = await sdk.getItems("Category,Vendor", 50);
40
+
41
+ // New way (recommended)
42
+ const items = await sdk.getItems({
43
+ relations: "Category,Vendor",
44
+ limit: 50,
45
+ timeStamp: "2025-01-01T00:00:00.000Z"
46
+ });
47
+ ```
48
+
49
+ ### Enhanced Error Handling
50
+
51
+ - Methods now return empty arrays instead of undefined on errors
52
+ - Less verbose logging for common API failures
53
+ - Consistent error handling across all methods
54
+
55
+ ### What's New in 3.2.0
56
+
57
+ - **Object-based parameters** for all 20+ collection methods
58
+ - **Timestamp filtering** to get only recent changes
59
+ - **Clean error handling** with minimal logging
60
+ - **Enhanced CLI** with browser selection and better defaults
61
+ - **Improved token management** with better error recovery
62
+
63
+ ---
64
+
65
+ ## Table of Contents
66
+
67
+ - [Another Unofficial Lightspeed Retail V3 API SDK](#another-unofficial-lightspeed-retail-v3-api-sdk)
68
+ - [**🆕 Recent Updates (v3.2.0)**](#-recent-updates-v320)
69
+ - [🚀 Key Features](#-key-features)
70
+ - [🔄 Migrating from 3.1.x](#-migrating-from-31x)
71
+ - [Table of Contents](#table-of-contents)
72
+ - [🚨 Important Update - New OAuth System](#-important-update---new-oauth-system)
73
+ - [Key Changes](#key-changes)
74
+ - [Interactive CLI](#interactive-cli)
75
+ - [Getting Started with the CLI](#getting-started-with-the-cli)
76
+ - [Available CLI Commands](#available-cli-commands)
77
+ - [Authentication \& Setup](#authentication--setup)
78
+ - [Storage Management](#storage-management)
79
+ - [Email Testing](#email-testing)
80
+ - [CLI Features](#cli-features)
81
+ - [Interactive Storage Selection](#interactive-storage-selection)
82
+ - [OAuth Authentication Flow](#oauth-authentication-flow)
83
+ - [Token Management](#token-management)
84
+ - [Manual Token Refresh](#manual-token-refresh)
85
+ - [Token Status Checking](#token-status-checking)
86
+ - [Database Setup Wizard](#database-setup-wizard)
87
+ - [Token Migration](#token-migration)
88
+ - [Security Features](#security-features)
89
+ - [Email Notifications](#email-notifications)
90
+ - [CLI Configuration](#cli-configuration)
91
+ - [CLI Examples](#cli-examples)
92
+ - [Features](#features)
93
+ - [Smart Token Management](#smart-token-management)
94
+ - [Token Priority Order](#token-priority-order)
95
+ - [Environment Variables](#environment-variables)
96
+ - [Installation](#installation)
97
+ - [Global CLI Installation (Recommended)](#global-cli-installation-recommended)
98
+ - [Local Installation](#local-installation)
99
+ - [Configuration](#configuration)
100
+ - [Quick Start](#quick-start)
101
+ - [Modern CLI-First Approach (Recommended)](#modern-cli-first-approach-recommended)
102
+ - [Alternative: Local Installation](#alternative-local-installation)
103
+ - [Basic Usage (In-Memory Storage)](#basic-usage-in-memory-storage)
104
+ - [Manual Token Management (Advanced)](#manual-token-management-advanced)
105
+ - [File-Based Storage](#file-based-storage)
106
+ - [Encrypted Storage (Recommended)](#encrypted-storage-recommended)
107
+ - [Database Storage (PostgreSQL, SQLite, and MongoDB)](#database-storage-postgresql-sqlite-and-mongodb)
108
+ - [Database Setup](#database-setup)
109
+ - [Option 1: Use the CLI (Recommended)](#option-1-use-the-cli-recommended)
110
+ - [Option 2: Manual Setup](#option-2-manual-setup)
111
+ - [PostgreSQL Schema](#postgresql-schema)
112
+ - [SQLite Schema](#sqlite-schema)
113
+ - [MongoDB Schema](#mongodb-schema)
114
+ - [Example: Using DatabaseTokenStorage](#example-using-databasetokenstorage)
115
+ - [Notes](#notes)
116
+ - [Custom Storage Interface (Advanced)](#custom-storage-interface-advanced)
117
+ - [CommonJS Usage](#commonjs-usage)
118
+ - [ES Modules (Recommended)](#es-modules-recommended)
119
+ - [CommonJS](#commonjs)
120
+ - [Migration from Previous Versions](#migration-from-previous-versions)
121
+ - [API Methods](#api-methods)
122
+ - [Enhanced Parameter Support](#enhanced-parameter-support)
123
+ - [Legacy Parameter Syntax (Still Supported)](#legacy-parameter-syntax-still-supported)
124
+ - [New Object-Based Parameter Syntax](#new-object-based-parameter-syntax)
125
+ - [Available Parameters](#available-parameters)
126
+ - [Core Resources](#core-resources)
127
+ - [Customers](#customers)
128
+ - [Items](#items)
129
+ - [Matrix Items](#matrix-items)
130
+ - [Categories](#categories)
131
+ - [Manufacturers](#manufacturers)
132
+ - [Vendors](#vendors)
133
+ - [Orders](#orders)
134
+ - [Sales](#sales)
135
+ - [Sale Lines](#sale-lines)
136
+ - [Account \& Configuration](#account--configuration)
137
+ - [Account Information](#account-information)
138
+ - [Employees](#employees)
139
+ - [System Configuration](#system-configuration)
140
+ - [Gift Cards \& Special Orders](#gift-cards--special-orders)
141
+ - [Images](#images)
142
+ - [Utility Methods](#utility-methods)
143
+ - [Error Handling](#error-handling)
144
+ - [**Automatic Error Recovery**](#automatic-error-recovery)
145
+ - [**Safe Return Types**](#safe-return-types)
146
+ - [**Enhanced Error Logging**](#enhanced-error-logging)
147
+ - [**Graceful Degradation**](#graceful-degradation)
148
+ - [Rate Limiting](#rate-limiting)
149
+ - [Pagination](#pagination)
150
+ - [Contributing](#contributing)
151
+ - [License](#license)
152
+ - [Disclaimer](#disclaimer)
153
+ - [More Info](#more-info)
6
154
 
7
155
  ## 🚨 Important Update - New OAuth System
8
156
 
9
- **Lightspeed has implemented a new OAuth authorization server.** This SDK has been updated to support the new endpoints and token rotation system.
157
+ **Lightspeed has implemented a new OAuth authorization server.** This SDK is fully updated to support the new endpoints and token rotation system.
10
158
 
11
159
  ### Key Changes
12
160
 
13
- - **NEW: Encrypted token storage** - Secure your tokens at rest with built-in AES-256-GCM encryption using Node.js crypto
14
- - **New OAuth endpoints** - Updated to use `https://cloud.lightspeedapp.com/auth/oauth/token`
15
- - **Token rotation** - Both access and refresh tokens now change with each refresh
16
- - **Token persistence** - Tokens must be stored between application restarts
17
- - **Longer token values** - Ensure your storage can handle the new token lengths
161
+ - **NEW: Encrypted token storage** Secure your tokens at rest with built-in AES-256-GCM encryption using Node.js crypto
162
+ - **New OAuth endpoints** Uses `https://cloud.lightspeedapp.com/auth/oauth/token`
163
+ - **Token rotation** Both access and refresh tokens now change with each refresh
164
+ - **Token persistence** Tokens must be stored between application restarts
165
+ - **Longer token values** Ensure your storage can handle the new token lengths
166
+
167
+ ## Interactive CLI
168
+
169
+ The SDK includes a powerful interactive CLI for easy setup, authentication, and token management. No coding required!
170
+
171
+ ### Getting Started with the CLI
172
+
173
+ The CLI provides an interactive way to:
174
+
175
+ - Authenticate with Lightspeed OAuth
176
+ - Manage tokens across different storage backends
177
+ - Set up database storage
178
+ - Migrate tokens between storage systems
179
+ - View account information
180
+
181
+ ### Available CLI Commands
182
+
183
+ > **Note**: The examples below assume global installation (`npm install -g lightspeed-retail-sdk`). If you installed locally, prefix commands with `npx` (e.g., `npx lightspeed-retail-sdk login`).
184
+
185
+ #### Authentication & Setup
186
+
187
+ ```bash
188
+ # Start OAuth authentication flow
189
+ lightspeed-retail-sdk login
190
+
191
+ # Start OAuth authentication with specific browser
192
+ lightspeed-retail-sdk login --browser firefox
193
+ lightspeed-retail-sdk login --browser "google chrome"
194
+ lightspeed-retail-sdk login --browser safari
195
+
196
+ # Check current token status
197
+ lightspeed-retail-sdk token-status
198
+
199
+ # Manually refresh stored access token
200
+ lightspeed-retail-sdk refresh-token
201
+
202
+ # View your account information
203
+ lightspeed-retail-sdk whoami
204
+ ```
205
+
206
+ #### Storage Management
207
+
208
+ ```bash
209
+ # Set up database storage (SQLite, Postgres, MongoDB)
210
+ lightspeed-retail-sdk setup-db
211
+
212
+ # Clear stored tokens
213
+ lightspeed-retail-sdk reset
214
+
215
+ # Migrate tokens between storage backends
216
+ lightspeed-retail-sdk migrate-tokens
217
+ ```
218
+
219
+ #### Email Testing
220
+
221
+ ```bash
222
+ # Test email notification system
223
+ lightspeed-retail-sdk test-email
224
+
225
+ # Test with custom account ID
226
+ lightspeed-retail-sdk test-email --account-id "YOUR-ACCOUNT-ID"
227
+ ```
228
+
229
+ ### CLI Features
230
+
231
+ #### Interactive Storage Selection
232
+
233
+ The CLI automatically prompts you to choose your preferred storage backend:
234
+
235
+ - **File Storage** - Simple JSON file storage
236
+ - **Encrypted File Storage** - AES-256-GCM encrypted file storage (recommended)
237
+ - **Encrypted Database Storage** - SQLite, PostgreSQL, or MongoDB (always encrypted)
238
+
239
+ #### OAuth Authentication Flow
240
+
241
+ ```bash
242
+ lightspeed-retail-sdk login
243
+ ```
244
+
245
+ The login process:
246
+
247
+ 1. Prompts for your Lightspeed credentials (if not in environment)
248
+ 2. Optionally lets you choose a specific browser
249
+ 3. Opens browser for OAuth authorization
250
+ 4. Automatically exchanges code for tokens
251
+ 5. Stores tokens in your chosen backend
252
+
253
+ **Note**: If no scopes are specified via environment variables or user input, the default scope `employee:all` will be used.
254
+
255
+ **Browser Options:**
256
+
257
+ ```bash
258
+ # Use default browser
259
+ lightspeed-retail-sdk login
260
+
261
+ # Specify browser via command line
262
+ lightspeed-retail-sdk login --browser firefox
263
+ lightspeed-retail-sdk login --browser "google chrome"
264
+
265
+ # Interactive browser selection (when no --browser flag is used)
266
+ # The CLI will ask if you want to choose a specific browser
267
+ ```
268
+
269
+ #### Token Management
270
+
271
+ ##### Manual Token Refresh
272
+
273
+ ```bash
274
+ lightspeed-retail-sdk refresh-token
275
+ ```
276
+
277
+ Use this command to:
278
+
279
+ - Test your refresh token before it expires
280
+ - Force a token refresh for testing purposes
281
+ - Update access tokens without full re-authentication
282
+ - Verify that your stored credentials are working
283
+
284
+ The command will:
285
+
286
+ - Show current token expiration status
287
+ - Attempt to refresh using stored refresh token
288
+ - Display the new token information
289
+ - Handle token rotation if enabled by Lightspeed
290
+
291
+ ##### Token Status Checking
292
+
293
+ ```bash
294
+ lightspeed-retail-sdk token-status
295
+ ```
296
+
297
+ Shows detailed information about your stored tokens including expiration times.
298
+
299
+ #### Database Setup Wizard
300
+
301
+ ```bash
302
+ lightspeed-retail-sdk setup-db
303
+ ```
304
+
305
+ - Guides you through database connection setup
306
+ - Creates required tables/collections
307
+ - Tests database connectivity
308
+ - Supports local and cloud databases
309
+
310
+ #### Token Migration
311
+
312
+ ```bash
313
+ lightspeed-retail-sdk migrate-tokens
314
+ ```
315
+
316
+ - Move tokens between any supported storage backends
317
+ - Automatically creates destination storage if needed
318
+ - Confirms before overwriting existing tokens
319
+ - Validates successful migration
320
+
321
+ #### Security Features
322
+
323
+ - **Database tokens are always encrypted** - Uses AES-256-GCM encryption automatically
324
+ - **Secure credential prompting** - Sensitive inputs are handled securely
325
+ - **Environment variable support** - Use `.env` files for configuration
326
+ - **Connection cleanup** - Proper database connection management
327
+
328
+ #### Email Notifications
329
+
330
+ The SDK can automatically send email alerts when token refresh fails:
331
+
332
+ ```bash
333
+ # Configure SMTP settings in your .env file
334
+ SMTP_HOST=smtp.gmail.com
335
+ SMTP_PORT=587
336
+ SMTP_SECURE=false # true for 465, false for other ports
337
+ SMTP_USER=your-email@gmail.com
338
+ SMTP_PASS=your-app-password # Use app passwords for Gmail
339
+ SMTP_FROM=your-email@gmail.com # Optional, defaults to SMTP_USER
340
+ ALERT_EMAIL=admin@yourcompany.com
341
+
342
+ # Test the email system
343
+ lightspeed-retail-sdk test-email
344
+ ```
345
+
346
+ **Email Features:**
347
+
348
+ - Automatic alerts on token refresh failures
349
+ - Detailed error information and recovery steps
350
+ - Configurable SMTP settings
351
+ - Built-in test command for validation
352
+
353
+ ### CLI Configuration
354
+
355
+ You can configure the CLI using environment variables:
356
+
357
+ ```bash
358
+ # Token storage location
359
+ LIGHTSPEED_TOKEN_FILE=./tokens/encrypted-tokens.json
360
+
361
+ # Encryption key for secure storage
362
+ LIGHTSPEED_ENCRYPTION_KEY=your_64_char_hex_key
363
+
364
+ # Database connections (for database storage)
365
+ LIGHTSPEED_POSTGRES_URL=postgres://user:pass@host:5432/db
366
+ LIGHTSPEED_MONGO_URL=mongodb://localhost:27017/lightspeed
367
+
368
+ # OAuth credentials
369
+ LIGHTSPEED_CLIENT_ID=your_client_id
370
+ LIGHTSPEED_CLIENT_SECRET=your_client_secret
371
+ LIGHTSPEED_ACCOUNT_ID=your_account_id
372
+ LIGHTSPEED_REDIRECT_URL=your_lightspeed_redirect_url
373
+
374
+ # Optional: OAuth scopes (defaults to "employee:all" if not specified)
375
+ LIGHTSPEED_SCOPES=employee:all inventory:all
376
+ ```
377
+
378
+ ### CLI Examples
379
+
380
+ **Complete setup from scratch:**
381
+
382
+ ```bash
383
+ # 1. Generate encryption key and add to .env
384
+ node -e "console.log('LIGHTSPEED_ENCRYPTION_KEY=' + require('crypto').randomBytes(32).toString('hex'))"
385
+
386
+ # 2. Set up database storage
387
+ lightspeed-retail-sdk setup-db
388
+
389
+ # 3. Authenticate and store tokens (with browser choice)
390
+ lightspeed-retail-sdk login --browser firefox
391
+
392
+ # 4. Verify setup
393
+ lightspeed-retail-sdk whoami
394
+ ```
395
+
396
+ **Migrate from file to database:**
397
+
398
+ ```bash
399
+ lightspeed-retail-sdk migrate-tokens
400
+ # Select "Encrypted File" as source
401
+ # Select "Encrypted Database" as destination
402
+ # Choose your database type and connection
403
+ ```
404
+
405
+ **Check token status:**
406
+
407
+ ```bash
408
+ lightspeed-retail-sdk token-status
409
+ # Shows token validity, expiration, and storage location
410
+ ```
411
+
412
+ The CLI makes it easy to get started with the SDK without writing any configuration code!
18
413
 
19
414
  ## Features
20
415
 
21
- - **NEW: Encrypted token storage** - Secure your tokens at rest with built-in AES-256-GCM encryption using Node.js crypto
22
- - Easy-to-use methods for interacting with various Lightspeed Retail endpoints.
23
- - Built-in handling of API rate limits.
24
- - Automatic token management for authentication.
25
- - **NEW: Auto-retry on authentication errors** - Automatically refreshes tokens and retries failed requests.
26
- - Support for paginated responses from the Lightspeed API.
27
- - Retry logic for handling transient network issues.
28
- - **NEW: Flexible token storage** - File-based, database, or custom storage options.
29
- - **NEW: Advanced search capabilities** - Search items and customers with flexible queries.
30
- - **NEW: Bulk operations** - Update multiple items efficiently.
31
- - **NEW: Inventory management** - Low stock alerts and category-based queries.
32
- - Support for both CommonJS and ES modules.
416
+ - **Interactive CLI** Complete command-line interface for authentication, token management, and database setup
417
+ - **Encrypted token storage** Secure your tokens at rest with built-in AES-256-GCM encryption using Node.js crypto
418
+ - **Email notifications** Automatic alerts for token refresh failures with configurable SMTP settings
419
+ - **Flexible storage backends** File-based, encrypted, database (SQLite, PostgreSQL, MongoDB), or custom storage options
420
+ - **Smart token management** Automatic refresh, rotation handling, and persistent storage
421
+ - **Auto-retry on authentication errors** Automatically refreshes tokens and retries failed requests
422
+ - Easy-to-use methods for all major Lightspeed Retail endpoints
423
+ - Built-in handling of API rate limits and pagination
424
+ - Retry logic for transient network issues
425
+ - Advanced search capabilities for items and customers
426
+ - Bulk operations for efficient data updates
427
+ - Inventory management with low stock alerts and category queries
428
+ - Support for both CommonJS and ES modules
33
429
 
34
430
  ## Smart Token Management
35
431
 
@@ -60,6 +456,19 @@ LIGHTSPEED_CLIENT_SECRET=your_client_secret
60
456
  LIGHTSPEED_ACCESS_TOKEN=your_access_token
61
457
  LIGHTSPEED_REFRESH_TOKEN=your_refresh_token
62
458
  LIGHTSPEED_TOKEN_EXPIRES_AT=2025-01-01T00:00:00.000Z
459
+
460
+ # Storage Configuration (CLI only)
461
+ LIGHTSPEED_TOKEN_FILE=./tokens/encrypted-tokens.json
462
+ LIGHTSPEED_ENCRYPTION_KEY=your-64-character-encryption-key
463
+
464
+ # Email Notifications (Optional)
465
+ SMTP_HOST=smtp.gmail.com
466
+ SMTP_PORT=587
467
+ SMTP_SECURE=false
468
+ SMTP_USER=your-email@gmail.com
469
+ SMTP_PASS=your-app-password
470
+ SMTP_FROM=your-email@gmail.com
471
+ ALERT_EMAIL=admin@yourcompany.com
63
472
  ```
64
473
 
65
474
  ⚠️ **Note**: Environment variables are used as fallback when no stored tokens are found. Once tokens are stored via your chosen storage method, those take priority.
@@ -70,8 +479,160 @@ LIGHTSPEED_TOKEN_EXPIRES_AT=2025-01-01T00:00:00.000Z
70
479
  npm install lightspeed-retail-sdk
71
480
  ```
72
481
 
482
+ ### Global CLI Installation (Recommended)
483
+
484
+ For the best experience, install the SDK globally to access the CLI from anywhere:
485
+
486
+ ```bash
487
+ npm install -g lightspeed-retail-sdk
488
+ ```
489
+
490
+ Once installed globally, you can use the CLI directly:
491
+
492
+ ```bash
493
+ lightspeed-retail-sdk help
494
+ lightspeed-retail-sdk login
495
+ lightspeed-retail-sdk token-status
496
+ lightspeed-retail-sdk whoami
497
+ ```
498
+
499
+ ### Local Installation
500
+
501
+ If you prefer local installation or are using the SDK in a specific project:
502
+
503
+ ```bash
504
+ npm install lightspeed-retail-sdk
505
+ ```
506
+
507
+ Then use the CLI with `npx`:
508
+
509
+ ```bash
510
+ npx lightspeed-retail-sdk help
511
+ npx lightspeed-retail-sdk login
512
+ npx lightspeed-retail-sdk token-status
513
+ ```
514
+
515
+ Or add scripts to your `package.json`:
516
+
517
+ ```json
518
+ {
519
+ "scripts": {
520
+ "lightspeed-setup": "lightspeed-retail-sdk login",
521
+ "lightspeed-status": "lightspeed-retail-sdk token-status",
522
+ "lightspeed-refresh": "lightspeed-retail-sdk refresh-token"
523
+ }
524
+ }
525
+ ```
526
+
527
+ Then run:
528
+
529
+ ```bash
530
+ npm run lightspeed-setup
531
+ npm run lightspeed-status
532
+ ```
533
+
534
+ ### Configuration
535
+
536
+ Create a `.env` file in your project root (where you'll run the CLI commands) with your Lightspeed credentials:
537
+
538
+ ```bash
539
+ # Required OAuth credentials
540
+ LIGHTSPEED_CLIENT_ID=your_client_id
541
+ LIGHTSPEED_CLIENT_SECRET=your_client_secret
542
+ LIGHTSPEED_ACCOUNT_ID=your_account_id
543
+ LIGHTSPEED_REDIRECT_URL=your_redirect_url
544
+
545
+ # Optional: Storage configuration
546
+ LIGHTSPEED_TOKEN_FILE=./tokens/encrypted-tokens.json
547
+ LIGHTSPEED_ENCRYPTION_KEY=your_64_char_hex_key
548
+
549
+ # Optional: Database connections
550
+ LIGHTSPEED_POSTGRES_URL=postgres://user:pass@host:5432/db
551
+ LIGHTSPEED_MONGO_URL=mongodb://localhost:27017/lightspeed
552
+
553
+ # Optional: Email notifications
554
+ SMTP_HOST=smtp.gmail.com
555
+ SMTP_PORT=587
556
+ SMTP_SECURE=false
557
+ SMTP_USER=your-email@gmail.com
558
+ SMTP_PASS=your-app-password
559
+ ALERT_EMAIL=admin@yourcompany.com
560
+
561
+ # Optional: OAuth scopes (defaults to "employee:all")
562
+ LIGHTSPEED_SCOPES=employee:all
563
+ ```
564
+
565
+ Generate an encryption key for secure token storage:
566
+
567
+ ```bash
568
+ # Run this command to generate a secure encryption key
569
+ node -e "console.log('LIGHTSPEED_ENCRYPTION_KEY=' + require('crypto').randomBytes(32).toString('hex'))"
570
+ ```
571
+
572
+ Add the generated key to your `.env` file.
573
+
574
+ > **Note**: The CLI will read configuration from the `.env` file in your current working directory, making setup much easier by reducing the number of prompts.
575
+
73
576
  ## Quick Start
74
577
 
578
+ ### Modern CLI-First Approach (Recommended)
579
+
580
+ The easiest way to get started is using the interactive CLI to handle authentication:
581
+
582
+ ```bash
583
+ # 1. Install the SDK globally
584
+ npm install -g lightspeed-retail-sdk
585
+
586
+ # 2. Authenticate using CLI (one-time setup)
587
+ lightspeed-retail-sdk login
588
+
589
+ # 3. Use the SDK in your code
590
+ ```
591
+
592
+ #### Alternative: Local Installation
593
+
594
+ ```bash
595
+ # 1. Install the SDK locally
596
+ npm install lightspeed-retail-sdk
597
+
598
+ # 2. Authenticate using CLI (one-time setup)
599
+ npx lightspeed-retail-sdk login
600
+
601
+ # 3. Use the SDK in your code
602
+ ```
603
+
604
+ Then in your code:
605
+
606
+ ```javascript
607
+ import LightspeedRetailSDK, {
608
+ FileTokenStorage,
609
+ EncryptedTokenStorage,
610
+ } from "lightspeed-retail-sdk";
611
+ import dotenv from "dotenv";
612
+ dotenv.config();
613
+
614
+ // Use the same storage configuration as your CLI
615
+ const fileStorage = new FileTokenStorage(
616
+ process.env.LIGHTSPEED_TOKEN_FILE || "./tokens/encrypted-tokens.json"
617
+ );
618
+ const tokenStorage = process.env.LIGHTSPEED_ENCRYPTION_KEY
619
+ ? new EncryptedTokenStorage(
620
+ fileStorage,
621
+ process.env.LIGHTSPEED_ENCRYPTION_KEY
622
+ )
623
+ : fileStorage;
624
+
625
+ const api = new LightspeedRetailSDK({
626
+ accountID: process.env.LIGHTSPEED_ACCOUNT_ID,
627
+ clientID: process.env.LIGHTSPEED_CLIENT_ID,
628
+ clientSecret: process.env.LIGHTSPEED_CLIENT_SECRET,
629
+ tokenStorage,
630
+ });
631
+
632
+ // The SDK will automatically use stored tokens and refresh as needed
633
+ export default api;
634
+ ```
635
+
75
636
  ### Basic Usage (In-Memory Storage)
76
637
 
77
638
  ```javascript
@@ -88,7 +649,9 @@ const api = new LightspeedRetailSDK({
88
649
 
89
650
  ⚠️ **Warning**: Basic usage stores tokens in memory only. Tokens will be lost on application restart, which may cause issues with Lightspeed's new token rotation system.
90
651
 
91
- ### Recommended Usage (Persistent Storage)
652
+ ### Manual Token Management (Advanced)
653
+
654
+ If you prefer to handle authentication manually without the CLI:
92
655
 
93
656
  #### File-Based Storage
94
657
 
@@ -113,7 +676,7 @@ You can now store your tokens **encrypted at rest** using the built-in `Encrypte
113
676
  **Generate a key** (if you haven't already):
114
677
 
115
678
  ```bash
116
- npm run generate-key
679
+ node -e "console.log('LIGHTSPEED_ENCRYPTION_KEY=' + require('crypto').randomBytes(32).toString('hex'))"
117
680
  ```
118
681
 
119
682
  Add the generated key to your `.env` file:
@@ -125,8 +688,10 @@ LIGHTSPEED_ENCRYPTION_KEY=your_64_char_hex_key_here
125
688
  **Usage Example:**
126
689
 
127
690
  ```javascript
128
- import LightspeedRetailSDK, { FileTokenStorage } from "lightspeed-retail-sdk";
129
- import { EncryptedTokenStorage } from "lightspeed-retail-sdk/src/storage/TokenStorage.mjs";
691
+ import LightspeedRetailSDK, {
692
+ FileTokenStorage,
693
+ EncryptedTokenStorage,
694
+ } from "lightspeed-retail-sdk";
130
695
  import dotenv from "dotenv";
131
696
  dotenv.config();
132
697
 
@@ -157,225 +722,123 @@ Keep your encryption key secure and never commit it to version control!
157
722
 
158
723
  ---
159
724
 
160
- #### Database Storage (Built-in Base Class)
725
+ ## Database Storage (PostgreSQL, SQLite, and MongoDB)
161
726
 
162
- The SDK provides a `DatabaseTokenStorage` base class that you can extend:
727
+ ### Database Setup
163
728
 
164
- ```javascript
165
- import LightspeedRetailSDK, {
166
- DatabaseTokenStorage,
167
- } from "lightspeed-retail-sdk";
168
- import mysql from "mysql2/promise";
729
+ #### Option 1: Use the CLI (Recommended)
169
730
 
170
- class MySQLTokenStorage extends DatabaseTokenStorage {
171
- constructor(connectionConfig, userId) {
172
- super();
173
- this.config = connectionConfig;
174
- this.userId = userId;
175
- }
731
+ ```bash
732
+ lightspeed-retail-sdk setup-db
733
+ ```
176
734
 
177
- async getTokens() {
178
- const connection = await mysql.createConnection(this.config);
179
- try {
180
- const [rows] = await connection.execute(
181
- "SELECT access_token, refresh_token, expires_at FROM user_tokens WHERE user_id = ?",
182
- [this.userId]
183
- );
184
-
185
- if (rows.length === 0) {
186
- return { access_token: null, refresh_token: null, expires_at: null };
187
- }
188
-
189
- return {
190
- access_token: rows[0].access_token,
191
- refresh_token: rows[0].refresh_token,
192
- expires_at: rows[0].expires_at,
193
- };
194
- } finally {
195
- await connection.end();
196
- }
197
- }
735
+ The CLI will guide you through creating the required tables/collections for your database.
198
736
 
199
- async setTokens(tokens) {
200
- const connection = await mysql.createConnection(this.config);
201
- try {
202
- await connection.execute(
203
- `INSERT INTO user_tokens (user_id, access_token, refresh_token, expires_at, updated_at)
204
- VALUES (?, ?, ?, ?, NOW())
205
- ON DUPLICATE KEY UPDATE
206
- access_token = VALUES(access_token),
207
- refresh_token = VALUES(refresh_token),
208
- expires_at = VALUES(expires_at),
209
- updated_at = NOW()`,
210
- [
211
- this.userId,
212
- tokens.access_token,
213
- tokens.refresh_token,
214
- tokens.expires_at,
215
- ]
216
- );
217
- } finally {
218
- await connection.end();
219
- }
220
- }
221
- }
737
+ #### Option 2: Manual Setup
222
738
 
223
- // Usage
224
- const dbConfig = {
225
- host: "localhost",
226
- user: "your_user",
227
- password: "your_password",
228
- database: "your_database",
229
- };
739
+ If you prefer to create the database schema manually, use the schemas below:
230
740
 
231
- const api = new LightspeedRetailSDK({
232
- accountID: "Your Account No.",
233
- clientID: "Your client ID.",
234
- clientSecret: "Your client secret.",
235
- refreshToken: "Your initial refresh token.",
236
- tokenStorage: new MySQLTokenStorage(dbConfig, "user123"),
237
- });
741
+ ### PostgreSQL Schema
742
+
743
+ ```sql
744
+ CREATE TABLE oauth_tokens (
745
+ app_id TEXT PRIMARY KEY,
746
+ tokens JSONB NOT NULL
747
+ );
238
748
  ```
239
749
 
240
- #### PostgreSQL Example
750
+ - `app_id`: Used to support multiple apps or tenants (default is `"default"`).
751
+ - `tokens`: Stores the full token object as JSON.
241
752
 
242
- ```javascript
243
- import { DatabaseTokenStorage } from "lightspeed-retail-sdk";
244
- import pg from "pg";
753
+ ### SQLite Schema
245
754
 
246
- class PostgreSQLTokenStorage extends DatabaseTokenStorage {
247
- constructor(connectionString, userId) {
248
- super();
249
- this.connectionString = connectionString;
250
- this.userId = userId;
251
- }
755
+ ```sql
756
+ CREATE TABLE oauth_tokens (
757
+ app_id TEXT PRIMARY KEY,
758
+ tokens TEXT NOT NULL
759
+ );
760
+ ```
252
761
 
253
- async getTokens() {
254
- const client = new pg.Client(this.connectionString);
255
- await client.connect();
256
-
257
- try {
258
- const result = await client.query(
259
- "SELECT access_token, refresh_token, expires_at FROM user_tokens WHERE user_id = $1",
260
- [this.userId]
261
- );
262
-
263
- if (result.rows.length === 0) {
264
- return { access_token: null, refresh_token: null, expires_at: null };
265
- }
266
-
267
- const row = result.rows[0];
268
- return {
269
- access_token: row.access_token,
270
- refresh_token: row.refresh_token,
271
- expires_at: row.expires_at,
272
- };
273
- } finally {
274
- await client.end();
275
- }
276
- }
762
+ - `tokens` is stored as a JSON string.
277
763
 
278
- async setTokens(tokens) {
279
- const client = new pg.Client(this.connectionString);
280
- await client.connect();
281
-
282
- try {
283
- await client.query(
284
- `INSERT INTO user_tokens (user_id, access_token, refresh_token, expires_at, updated_at)
285
- VALUES ($1, $2, $3, $4, NOW())
286
- ON CONFLICT (user_id) DO UPDATE SET
287
- access_token = EXCLUDED.access_token,
288
- refresh_token = EXCLUDED.refresh_token,
289
- expires_at = EXCLUDED.expires_at,
290
- updated_at = NOW()`,
291
- [
292
- this.userId,
293
- tokens.access_token,
294
- tokens.refresh_token,
295
- tokens.expires_at,
296
- ]
297
- );
298
- } finally {
299
- await client.end();
300
- }
764
+ ### MongoDB Schema
765
+
766
+ For MongoDB, no manual schema creation is required. The SDK will create documents with this structure:
767
+
768
+ ```javascript
769
+ {
770
+ app_id: "default",
771
+ tokens: {
772
+ access_token: "...",
773
+ refresh_token: "...",
774
+ expires_at: "2025-01-01T00:00:00.000Z",
775
+ expires_in: 3600
301
776
  }
302
777
  }
303
778
  ```
304
779
 
305
- #### MongoDB Example
780
+ - The collection name is configurable (default: `oauth_tokens`)
781
+ - A unique index on `app_id` is automatically created
782
+
783
+ ---
784
+
785
+ ### Example: Using DatabaseTokenStorage
786
+
787
+ > **Note:** You can use local or cloud database connection strings (for example, Heroku Postgres, MongoDB Atlas, etc.) in all examples below.
306
788
 
307
789
  ```javascript
308
790
  import { DatabaseTokenStorage } from "lightspeed-retail-sdk";
309
- import { MongoClient } from "mongodb";
310
-
311
- class MongoTokenStorage extends DatabaseTokenStorage {
312
- constructor(connectionString, databaseName, userId) {
313
- super();
314
- this.connectionString = connectionString;
315
- this.databaseName = databaseName;
316
- this.userId = userId;
317
- }
318
791
 
319
- async getTokens() {
320
- const client = new MongoClient(this.connectionString);
321
- await client.connect();
322
-
323
- try {
324
- const db = client.db(this.databaseName);
325
- const collection = db.collection("user_tokens");
326
-
327
- const doc = await collection.findOne({ userId: this.userId });
328
-
329
- if (!doc) {
330
- return { access_token: null, refresh_token: null, expires_at: null };
331
- }
332
-
333
- return {
334
- access_token: doc.access_token,
335
- refresh_token: doc.refresh_token,
336
- expires_at: doc.expires_at,
337
- };
338
- } finally {
339
- await client.close();
340
- }
792
+ // PostgreSQL
793
+ const pgStorage = new DatabaseTokenStorage(
794
+ "postgres://user:pass@host:5432/dbname",
795
+ {
796
+ dbType: "postgres",
797
+ tableName: "oauth_tokens", // optional
798
+ appId: "default", // optional
341
799
  }
800
+ );
342
801
 
343
- async setTokens(tokens) {
344
- const client = new MongoClient(this.connectionString);
345
- await client.connect();
346
-
347
- try {
348
- const db = client.db(this.databaseName);
349
- const collection = db.collection("user_tokens");
350
-
351
- await collection.updateOne(
352
- { userId: this.userId },
353
- {
354
- $set: {
355
- access_token: tokens.access_token,
356
- refresh_token: tokens.refresh_token,
357
- expires_at: tokens.expires_at,
358
- updated_at: new Date(),
359
- },
360
- },
361
- { upsert: true }
362
- );
363
- } finally {
364
- await client.close();
365
- }
802
+ // SQLite
803
+ const sqliteStorage = new DatabaseTokenStorage("./tokens.sqlite", {
804
+ dbType: "sqlite",
805
+ tableName: "oauth_tokens", // optional
806
+ appId: "default", // optional
807
+ });
808
+
809
+ // MongoDB
810
+ const mongoStorage = new DatabaseTokenStorage(
811
+ "mongodb://localhost:27017/yourdb",
812
+ {
813
+ dbType: "mongodb",
814
+ tableName: "oauth_tokens", // optional (collection name)
815
+ appId: "default", // optional
366
816
  }
367
- }
817
+ );
368
818
  ```
369
819
 
370
- ### Custom Storage Interface
820
+ ---
821
+
822
+ ### Notes
823
+
824
+ - **You must create the table or collection before using the SDK.** The SDK does not auto-create tables or collections.
825
+ - For multi-tenant or multi-app setups, use a unique `appId` for each logical app.
826
+ - The SDK stores the entire token object (including access, refresh, and expiry) in the `tokens` field.
827
+ - For MongoDB, you may use any database name in your connection string; the collection name is configurable.
828
+
829
+ ---
830
+
831
+ ### Custom Storage Interface (Advanced)
832
+
833
+ > **Note:** Most users do not need to implement a custom storage backend. This is only for advanced use cases where you need to integrate with a non-standard storage system (for example, a custom API, key-value store, or enterprise secrets manager).
371
834
 
372
- Implement your own storage by creating a class with these methods:
835
+ To implement your own storage, create a class with these asynchronous methods:
373
836
 
374
837
  ```javascript
375
838
  class CustomTokenStorage {
376
839
  async getTokens() {
377
- // Return an object with: { access_token, refresh_token, expires_at }
378
- // Return null values if no tokens are stored
840
+ // Return an object: { access_token, refresh_token, expires_at }
841
+ // Return null if no tokens are stored
379
842
  }
380
843
 
381
844
  async setTokens(tokens) {
@@ -384,36 +847,6 @@ class CustomTokenStorage {
384
847
  }
385
848
  ```
386
849
 
387
- ### Database Schema Examples
388
-
389
- #### MySQL/PostgreSQL Schema
390
-
391
- ```sql
392
- CREATE TABLE user_tokens (
393
- user_id VARCHAR(255) PRIMARY KEY,
394
- access_token TEXT NOT NULL,
395
- refresh_token TEXT NOT NULL,
396
- expires_at TIMESTAMP NOT NULL,
397
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
398
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
399
- );
400
- ```
401
-
402
- #### MongoDB Schema
403
-
404
- ```javascript
405
- // No strict schema required, but documents will look like:
406
- {
407
- _id: ObjectId("..."),
408
- userId: "user123",
409
- access_token: "eyJ0eXAiOiJKV1Q...",
410
- refresh_token: "def5020058aac34d...",
411
- expires_at: "2025-07-02T16:09:42.069Z",
412
- created_at: ISODate("2025-07-02T15:09:42.069Z"),
413
- updated_at: ISODate("2025-07-02T15:09:42.069Z")
414
- }
415
- ```
416
-
417
850
  ## CommonJS Usage
418
851
 
419
852
  The SDK supports both ES modules and CommonJS:
@@ -444,16 +877,60 @@ If you're upgrading from a previous version:
444
877
  1. **Update your refresh token** by making one call to the new OAuth endpoint
445
878
  2. **Implement token storage** to persist the rotating tokens
446
879
  3. **Update token URLs** (handled automatically by the SDK)
447
- 4. **Ensure storage can handle longer tokens** (new tokens are significantly longer)
880
+ 4. **Ensure your storage can handle longer tokens** (new tokens are significantly longer)
448
881
 
449
882
  ## API Methods
450
883
 
884
+ ### Enhanced Parameter Support
885
+
886
+ **All main getter methods now support both legacy and new object-based parameters:**
887
+
888
+ #### Legacy Parameter Syntax (Still Supported)
889
+
890
+ ```javascript
891
+ const customers = await api.getCustomers("Contact");
892
+ const items = await api.getItems("Category,Vendor", 50);
893
+ const sales = await api.getSales("Customer", 25);
894
+ ```
895
+
896
+ #### New Object-Based Parameter Syntax
897
+
898
+ ```javascript
899
+ const customers = await api.getCustomers({
900
+ relations: "Contact",
901
+ limit: 50,
902
+ timeStamp: "2025-07-07T10:00:00.000Z",
903
+ sort: "timeStamp",
904
+ });
905
+
906
+ const items = await api.getItems({
907
+ relations: "Category,Vendor",
908
+ limit: 25,
909
+ timeStamp: "2025-07-07T10:00:00.000Z",
910
+ sort: "description",
911
+ });
912
+
913
+ const sales = await api.getSales({
914
+ relations: "Customer",
915
+ limit: 100,
916
+ timeStamp: "2025-07-07T10:00:00.000Z",
917
+ sort: "timeStamp",
918
+ });
919
+ ```
920
+
921
+ #### Available Parameters
922
+
923
+ - **relations**: Load related data (e.g., 'Category,Vendor')
924
+ - **limit**: Limit number of results (max 100) - triggers single-page request
925
+ - **timeStamp**: Filter by timestamp (ISO format) - retrieves records updated since this time
926
+ - **sort**: Sort results by field (e.g., 'timeStamp', 'description')
927
+
451
928
  ### Core Resources
452
929
 
453
930
  #### Customers
454
931
 
455
932
  - `getCustomer(id, relations)` - Fetch a specific customer by ID
456
- - `getCustomers(relations)` - Retrieve all customers
933
+ - `getCustomers(params)` - Retrieve all customers ✨ **Enhanced with object parameters**
457
934
  - `putCustomer(id, data)` - Update a customer
458
935
  - `postCustomer(data)` - Create a new customer
459
936
  - `searchCustomers(searchTerm, relations)` - Search customers by name or email
@@ -461,57 +938,74 @@ If you're upgrading from a previous version:
461
938
  #### Items
462
939
 
463
940
  - `getItem(id, relations)` - Fetch a specific item by ID
464
- - `getItems(relations, limit)` - Retrieve all items (or limited number if limit specified)
941
+ - `getItems(params)` - Retrieve all items **Enhanced with object parameters**
465
942
  - `getMultipleItems(items, relations)` - Get multiple items by IDs
466
943
  - `putItem(id, data)` - Update an item
467
944
  - `postItem(data)` - Create a new item
468
945
  - `getVendorItems(vendorID, relations)` - Get items by vendor
469
946
  - `searchItems(searchTerm, relations)` - Search items by description
470
- - `getItemsByCategory(categoryId, relations)` - Get items in a category
471
- - `getItemsWithLowStock(threshold, relations)` - Get items below stock threshold
947
+ - `getItemsByCategory(params)` - Get items in a category ✨ **Enhanced with object parameters**
948
+ - `getItemsWithLowStock(params)` - Get items below stock threshold ✨ **Enhanced with object parameters**
472
949
  - `updateMultipleItems(updates)` - Bulk update multiple items
473
950
 
951
+ **Enhanced getItems Examples:**
952
+
953
+ ```javascript
954
+ // Legacy usage (still works)
955
+ const items = await api.getItems("Category,Vendor", 50);
956
+
957
+ // New object-based usage with timestamp filtering
958
+ const recentItems = await api.getItems({
959
+ timeStamp: "2025-07-07T10:00:00.000Z", // Items updated since this timestamp
960
+ relations: "Category,Vendor",
961
+ sort: "timeStamp",
962
+ });
963
+
964
+ // Basic usage with relations only
965
+ const itemsWithCategories = await api.getItems({ relations: "Category" });
966
+ ```
967
+
474
968
  #### Matrix Items
475
969
 
476
970
  - `getMatrixItem(id, relations)` - Fetch a specific matrix item by ID
477
- - `getMatrixItems(relations)` - Retrieve all matrix items
971
+ - `getMatrixItems(params)` - Retrieve all matrix items ✨ **Enhanced with object parameters**
478
972
  - `putMatrixItem(id, data)` - Update a matrix item
479
973
  - `postMatrixItem(data)` - Create a new matrix item
480
974
 
481
975
  #### Categories
482
976
 
483
977
  - `getCategory(id, relations)` - Fetch a specific category by ID
484
- - `getCategories(relations)` - Retrieve all categories
978
+ - `getCategories(params)` - Retrieve all categories ✨ **Enhanced with object parameters**
485
979
  - `putCategory(id, data)` - Update a category
486
980
  - `postCategory(data)` - Create a new category
487
981
 
488
982
  #### Manufacturers
489
983
 
490
984
  - `getManufacturer(id, relations)` - Fetch a specific manufacturer by ID
491
- - `getManufacturers(relations)` - Retrieve all manufacturers
985
+ - `getManufacturers(params)` - Retrieve all manufacturers ✨ **Enhanced with object parameters**
492
986
  - `putManufacturer(id, data)` - Update a manufacturer
493
987
  - `postManufacturer(data)` - Create a new manufacturer
494
988
 
495
989
  #### Vendors
496
990
 
497
991
  - `getVendor(id, relations)` - Fetch a specific vendor by ID
498
- - `getVendors(relations)` - Retrieve all vendors
992
+ - `getVendors(params)` - Retrieve all vendors ✨ **Enhanced with object parameters**
499
993
  - `putVendor(id, data)` - Update a vendor
500
994
  - `postVendor(data)` - Create a new vendor
501
995
 
502
996
  #### Orders
503
997
 
504
998
  - `getOrder(id, relations)` - Fetch a specific order by ID
505
- - `getOrders(relations)` - Retrieve all orders
999
+ - `getOrders(params)` - Retrieve all orders ✨ **Enhanced with object parameters**
506
1000
  - `getOrdersByVendorID(id, relations)` - Get orders by vendor
507
1001
  - `getOpenOrdersByVendorID(id, relations)` - Get open orders by vendor
508
1002
 
509
1003
  #### Sales
510
1004
 
511
1005
  - `getSale(id, relations)` - Fetch a specific sale by ID
512
- - `getSales(relations)` - Retrieve all sales
1006
+ - `getSales(params)` - Retrieve all sales ✨ **Enhanced with object parameters**
513
1007
  - `getMultipleSales(saleIDs, relations)` - Get multiple sales by IDs
514
- - `getSalesByDateRange(startDate, endDate, relations)` - Get sales in date range
1008
+ - `getSalesByDateRange(params)` - Get sales in date range ✨ **Enhanced with object parameters**
515
1009
  - `putSale(id, data)` - Update a sale
516
1010
  - `postSale(data)` - Create a new sale
517
1011
 
@@ -529,26 +1023,26 @@ If you're upgrading from a previous version:
529
1023
 
530
1024
  #### Employees
531
1025
 
532
- - `getEmployees(relations)` - Get all employees
1026
+ - `getEmployees(params)` - Get all employees ✨ **Enhanced with object parameters**
533
1027
  - `getEmployee(id, relations)` - Get a specific employee
534
1028
 
535
1029
  #### System Configuration
536
1030
 
537
- - `getCustomerTypes(relations)` - Get customer types
538
- - `getRegisters(relations)` - Get registers/shops
539
- - `getPaymentTypes(relations)` - Get payment types
540
- - `getTaxClasses(relations)` - Get tax classes
541
- - `getItemAttributes(relations)` - Get item attributes
1031
+ - `getCustomerTypes(params)` - Get customer types ✨ **Enhanced with object parameters**
1032
+ - `getRegisters(params)` - Get registers/shops ✨ **Enhanced with object parameters**
1033
+ - `getPaymentTypes(params)` - Get payment types ✨ **Enhanced with object parameters**
1034
+ - `getTaxClasses(params)` - Get tax classes ✨ **Enhanced with object parameters**
1035
+ - `getItemAttributes(params)` - Get item attributes ✨ **Enhanced with object parameters**
542
1036
 
543
1037
  ### Gift Cards & Special Orders
544
1038
 
545
- - `getGiftCards(relations)` - Get all gift cards
1039
+ - `getGiftCards(params)` - Get all gift cards ✨ **Enhanced with object parameters**
546
1040
  - `getGiftCard(id, relations)` - Get a specific gift card by code
547
- - `getSpecialOrders(relations)` - Get special orders
1041
+ - `getSpecialOrders(params)` - Get special orders ✨ **Enhanced with object parameters**
548
1042
 
549
1043
  ### Images
550
1044
 
551
- - `getImages(relations)` - Get all images
1045
+ - `getImages(params)` - Get all images ✨ **Enhanced with object parameters**
552
1046
  - `postImage(imageFilePath, metadata)` - Upload an image
553
1047
 
554
1048
  ### Utility Methods
@@ -559,18 +1053,54 @@ If you're upgrading from a previous version:
559
1053
 
560
1054
  ## Error Handling
561
1055
 
562
- The SDK includes comprehensive error handling with automatic retries for transient failures:
1056
+ The SDK includes comprehensive error handling with automatic retries for transient failures and robust safety guarantees:
1057
+
1058
+ ### **Automatic Error Recovery**
1059
+
1060
+ - **Retry Logic**: Automatic retries for network errors and 5xx server errors
1061
+ - **401 Handling**: Automatic token refresh and request retry on authentication failures
1062
+ - **Rate Limiting**: Intelligent delays when approaching API rate limits
1063
+
1064
+ ### **Safe Return Types**
1065
+
1066
+ All GET methods are guaranteed to return consistent data types, never `undefined`:
563
1067
 
564
1068
  ```javascript
565
1069
  try {
566
- const item = await api.getItem(123);
567
- console.log(item);
1070
+ // These methods ALWAYS return arrays (never undefined)
1071
+ const items = await api.getItems({ timeStamp: "2025-07-07T10:00:00Z" });
1072
+ const customers = await api.getCustomers();
1073
+ const categories = await api.getCategories();
1074
+
1075
+ // Safe to access array properties without checking for undefined
1076
+ console.log(`Found ${items.length} items`);
1077
+
1078
+ // Even on API errors, you get an empty array
1079
+ if (items.length === 0) {
1080
+ console.log("No items found or API error occurred");
1081
+ }
568
1082
  } catch (error) {
569
- console.error("API Error:", error.message);
570
- // Error details are automatically logged by the SDK
1083
+ console.error("SDK Error:", error.message);
1084
+ // Detailed error logging is handled automatically by the SDK
571
1085
  }
572
1086
  ```
573
1087
 
1088
+ ### **Enhanced Error Logging**
1089
+
1090
+ When errors occur, the SDK provides detailed logging including:
1091
+
1092
+ - Request URLs and parameters
1093
+ - HTTP status codes and response data
1094
+ - Helpful context for debugging
1095
+ - Email notifications (when configured) for token refresh failures
1096
+
1097
+ ### **Graceful Degradation**
1098
+
1099
+ - API errors don't crash your application
1100
+ - Empty arrays returned instead of undefined
1101
+ - Detailed error messages logged for debugging
1102
+ - Automatic fallback behavior for common scenarios
1103
+
574
1104
  ## Rate Limiting
575
1105
 
576
1106
  The SDK automatically handles Lightspeed's API rate limits by: