lightspeed-retail-sdk 2.0.13 → 3.0.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 +317 -38
- package/dist/index.cjs +982 -0
- package/{index.mjs → dist/index.mjs} +323 -224
- package/dist/src/core/LightspeedSDK.cjs +261 -0
- package/dist/src/core/LightspeedSDK.mjs +273 -0
- package/dist/src/storage/TokenStorage.cjs +95 -0
- package/dist/src/storage/TokenStorage.mjs +97 -0
- package/package.json +34 -7
- package/index.cjs +0 -1035
package/README.md
CHANGED
|
@@ -2,18 +2,65 @@
|
|
|
2
2
|
|
|
3
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.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Current Version: 3.0.0** - Updated with new OAuth system support and enhanced token management.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
## 🚨 Important Update - New OAuth System
|
|
8
|
+
|
|
9
|
+
**Lightspeed has implemented a new OAuth authorization server.** This SDK has been updated to support the new endpoints and token rotation system.
|
|
10
|
+
|
|
11
|
+
### Key Changes
|
|
12
|
+
|
|
13
|
+
- **New OAuth endpoints** - Updated to use `https://cloud.lightspeedapp.com/auth/oauth/token`
|
|
14
|
+
- **Token rotation** - Both access and refresh tokens now change with each refresh
|
|
15
|
+
- **Token persistence** - Tokens must be stored between application restarts
|
|
16
|
+
- **Longer token values** - Ensure your storage can handle the new token lengths
|
|
9
17
|
|
|
10
18
|
## Features
|
|
11
19
|
|
|
12
20
|
- Easy-to-use methods for interacting with various Lightspeed Retail endpoints.
|
|
13
21
|
- Built-in handling of API rate limits.
|
|
14
22
|
- Automatic token management for authentication.
|
|
23
|
+
- **NEW: Auto-retry on authentication errors** - Automatically refreshes tokens and retries failed requests.
|
|
15
24
|
- Support for paginated responses from the Lightspeed API.
|
|
16
25
|
- Retry logic for handling transient network issues.
|
|
26
|
+
- **NEW: Flexible token storage** - File-based, database, or custom storage options.
|
|
27
|
+
- **NEW: Advanced search capabilities** - Search items and customers with flexible queries.
|
|
28
|
+
- **NEW: Bulk operations** - Update multiple items efficiently.
|
|
29
|
+
- **NEW: Inventory management** - Low stock alerts and category-based queries.
|
|
30
|
+
- Support for both CommonJS and ES modules.
|
|
31
|
+
|
|
32
|
+
## Smart Token Management
|
|
33
|
+
|
|
34
|
+
The SDK intelligently manages tokens with these features:
|
|
35
|
+
|
|
36
|
+
- **Automatic refresh** - Tokens are refreshed before they expire (1-minute buffer)
|
|
37
|
+
- **Auto-retry on 401 errors** - If a token is invalid, the SDK automatically refreshes and retries the request
|
|
38
|
+
- **Persistent storage priority** - Always checks stored tokens first, falls back to environment variables
|
|
39
|
+
- **Token rotation support** - Handles Lightspeed's new token rotation system seamlessly
|
|
40
|
+
|
|
41
|
+
### Token Priority Order
|
|
42
|
+
|
|
43
|
+
1. **Stored tokens** (from your chosen storage method)
|
|
44
|
+
2. **Environment variables** (fallback)
|
|
45
|
+
3. **Automatic refresh** (when expired)
|
|
46
|
+
|
|
47
|
+
## Environment Variables
|
|
48
|
+
|
|
49
|
+
For development and testing, you can use environment variables:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Required
|
|
53
|
+
LIGHTSPEED_ACCOUNT_ID=your_account_id
|
|
54
|
+
LIGHTSPEED_CLIENT_ID=your_client_id
|
|
55
|
+
LIGHTSPEED_CLIENT_SECRET=your_client_secret
|
|
56
|
+
|
|
57
|
+
# Optional (for initial setup)
|
|
58
|
+
LIGHTSPEED_ACCESS_TOKEN=your_access_token
|
|
59
|
+
LIGHTSPEED_REFRESH_TOKEN=your_refresh_token
|
|
60
|
+
LIGHTSPEED_TOKEN_EXPIRES_AT=2025-01-01T00:00:00.000Z
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
⚠️ **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.
|
|
17
64
|
|
|
18
65
|
## Installation
|
|
19
66
|
|
|
@@ -21,61 +68,292 @@ A JavaScript SDK for interacting with the Lightspeed Retail API. This SDK provid
|
|
|
21
68
|
npm install lightspeed-retail-sdk
|
|
22
69
|
```
|
|
23
70
|
|
|
24
|
-
##
|
|
71
|
+
## Quick Start
|
|
25
72
|
|
|
26
|
-
|
|
73
|
+
### Basic Usage (In-Memory Storage)
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
27
76
|
import LightspeedRetailSDK from "lightspeed-retail-sdk";
|
|
28
77
|
|
|
29
78
|
const api = new LightspeedRetailSDK({
|
|
30
79
|
accountID: "Your Account No.",
|
|
31
80
|
clientID: "Your client ID.",
|
|
32
81
|
clientSecret: "Your client secret.",
|
|
33
|
-
refreshToken: "Your refresh token.",
|
|
82
|
+
refreshToken: "Your initial refresh token.",
|
|
83
|
+
// No tokenStorage = uses InMemoryTokenStorage by default
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
⚠️ **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.
|
|
88
|
+
|
|
89
|
+
### Recommended Usage (Persistent Storage)
|
|
90
|
+
|
|
91
|
+
#### File-Based Storage
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
import LightspeedRetailSDK, { FileTokenStorage } from "lightspeed-retail-sdk";
|
|
95
|
+
|
|
96
|
+
const api = new LightspeedRetailSDK({
|
|
97
|
+
accountID: "Your Account No.",
|
|
98
|
+
clientID: "Your client ID.",
|
|
99
|
+
clientSecret: "Your client secret.",
|
|
100
|
+
refreshToken: "Your initial refresh token.",
|
|
101
|
+
tokenStorage: new FileTokenStorage("./lightspeed-tokens.json"),
|
|
34
102
|
});
|
|
35
103
|
|
|
36
|
-
export default api
|
|
104
|
+
export default api;
|
|
37
105
|
```
|
|
38
106
|
|
|
39
|
-
|
|
107
|
+
#### Custom Storage (Database Example)
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
import LightspeedRetailSDK from "lightspeed-retail-sdk";
|
|
111
|
+
|
|
112
|
+
class DatabaseTokenStorage {
|
|
113
|
+
constructor(userId) {
|
|
114
|
+
this.userId = userId;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async getTokens() {
|
|
118
|
+
const user = await db.users.findById(this.userId);
|
|
119
|
+
return {
|
|
120
|
+
access_token: user.lightspeed_access_token,
|
|
121
|
+
refresh_token: user.lightspeed_refresh_token,
|
|
122
|
+
expires_at: user.lightspeed_token_expires_at,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
40
125
|
|
|
126
|
+
async setTokens(tokens) {
|
|
127
|
+
await db.users.update(this.userId, {
|
|
128
|
+
lightspeed_access_token: tokens.access_token,
|
|
129
|
+
lightspeed_refresh_token: tokens.refresh_token,
|
|
130
|
+
lightspeed_token_expires_at: tokens.expires_at,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const api = new LightspeedRetailSDK({
|
|
136
|
+
accountID: "Your Account No.",
|
|
137
|
+
clientID: "Your client ID.",
|
|
138
|
+
clientSecret: "Your client secret.",
|
|
139
|
+
refreshToken: "Your initial refresh token.",
|
|
140
|
+
tokenStorage: new DatabaseTokenStorage(userId),
|
|
141
|
+
});
|
|
41
142
|
```
|
|
143
|
+
|
|
144
|
+
## Example Requests
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
// Basic item request
|
|
42
148
|
const item = await api.getItem(7947, '["Category", "Images"]');
|
|
43
149
|
console.log(item);
|
|
44
150
|
|
|
45
|
-
|
|
151
|
+
// Get all items
|
|
152
|
+
const allItems = await api.getItems();
|
|
153
|
+
|
|
154
|
+
// Get limited number of items
|
|
155
|
+
const firstTenItems = await api.getItems(null, 10);
|
|
156
|
+
|
|
157
|
+
// Search for items
|
|
158
|
+
const searchResults = await api.searchItems("iPhone", '["Category"]');
|
|
159
|
+
|
|
160
|
+
// Get low stock items
|
|
161
|
+
const lowStockItems = await api.getItemsWithLowStock(10, '["Category"]');
|
|
162
|
+
|
|
163
|
+
// Bulk update items
|
|
164
|
+
const updates = [
|
|
165
|
+
{ itemID: 123, data: { description: "Updated description" } },
|
|
166
|
+
{ itemID: 456, data: { qoh: 50 } },
|
|
167
|
+
];
|
|
168
|
+
const results = await api.updateMultipleItems(updates);
|
|
169
|
+
|
|
170
|
+
// Check API connection
|
|
171
|
+
const status = await api.ping();
|
|
172
|
+
console.log(status);
|
|
173
|
+
|
|
174
|
+
// Check API connection
|
|
175
|
+
const status = await api.ping();
|
|
176
|
+
console.log(status);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Token Storage Options
|
|
180
|
+
|
|
181
|
+
### Built-in Storage Classes
|
|
182
|
+
|
|
183
|
+
1. **InMemoryTokenStorage** (default) - Stores tokens in memory only
|
|
184
|
+
2. **FileTokenStorage** - Stores tokens in a JSON file
|
|
185
|
+
|
|
186
|
+
### Custom Storage Interface
|
|
187
|
+
|
|
188
|
+
Implement your own storage by creating a class with these methods:
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
class CustomTokenStorage {
|
|
192
|
+
async getTokens() {
|
|
193
|
+
// Return an object with: { access_token, refresh_token, expires_at }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async setTokens(tokens) {
|
|
197
|
+
// Store the tokens object: { access_token, refresh_token, expires_at, expires_in }
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Migration from Previous Versions
|
|
203
|
+
|
|
204
|
+
If you're upgrading from a previous version:
|
|
205
|
+
|
|
206
|
+
1. **Update your refresh token** by making one call to the new OAuth endpoint
|
|
207
|
+
2. **Implement token storage** to persist the rotating tokens
|
|
208
|
+
3. **Update token URLs** (handled automatically by the SDK)
|
|
209
|
+
4. **Ensure storage can handle longer tokens** (new tokens are significantly longer)
|
|
210
|
+
|
|
211
|
+
## API Methods
|
|
212
|
+
|
|
213
|
+
### Core Resources
|
|
214
|
+
|
|
215
|
+
#### Customers
|
|
216
|
+
|
|
217
|
+
- `getCustomer(id, relations)` - Fetch a specific customer by ID
|
|
218
|
+
- `getCustomers(relations)` - Retrieve all customers
|
|
219
|
+
- `putCustomer(id, data)` - Update a customer
|
|
220
|
+
- `postCustomer(data)` - Create a new customer
|
|
221
|
+
- `searchCustomers(searchTerm, relations)` - Search customers by name or email
|
|
222
|
+
|
|
223
|
+
#### Items
|
|
224
|
+
|
|
225
|
+
- `getItem(id, relations)` - Fetch a specific item by ID
|
|
226
|
+
- `getItems(relations, limit)` - Retrieve all items (or limited number if limit specified)
|
|
227
|
+
- `getMultipleItems(items, relations)` - Get multiple items by IDs
|
|
228
|
+
- `putItem(id, data)` - Update an item
|
|
229
|
+
- `postItem(data)` - Create a new item
|
|
230
|
+
- `getVendorItems(vendorID, relations)` - Get items by vendor
|
|
231
|
+
- `searchItems(searchTerm, relations)` - Search items by description
|
|
232
|
+
- `getItemsByCategory(categoryId, relations)` - Get items in a category
|
|
233
|
+
- `getItemsWithLowStock(threshold, relations)` - Get items below stock threshold
|
|
234
|
+
- `updateMultipleItems(updates)` - Bulk update multiple items
|
|
235
|
+
|
|
236
|
+
#### Matrix Items
|
|
237
|
+
|
|
238
|
+
- `getMatrixItem(id, relations)` - Fetch a specific matrix item by ID
|
|
239
|
+
- `getMatrixItems(relations)` - Retrieve all matrix items
|
|
240
|
+
- `putMatrixItem(id, data)` - Update a matrix item
|
|
241
|
+
- `postMatrixItem(data)` - Create a new matrix item
|
|
242
|
+
|
|
243
|
+
#### Categories
|
|
244
|
+
|
|
245
|
+
- `getCategory(id, relations)` - Fetch a specific category by ID
|
|
246
|
+
- `getCategories(relations)` - Retrieve all categories
|
|
247
|
+
- `putCategory(id, data)` - Update a category
|
|
248
|
+
- `postCategory(data)` - Create a new category
|
|
249
|
+
|
|
250
|
+
#### Manufacturers
|
|
251
|
+
|
|
252
|
+
- `getManufacturer(id, relations)` - Fetch a specific manufacturer by ID
|
|
253
|
+
- `getManufacturers(relations)` - Retrieve all manufacturers
|
|
254
|
+
- `putManufacturer(id, data)` - Update a manufacturer
|
|
255
|
+
- `postManufacturer(data)` - Create a new manufacturer
|
|
256
|
+
|
|
257
|
+
#### Vendors
|
|
258
|
+
|
|
259
|
+
- `getVendor(id, relations)` - Fetch a specific vendor by ID
|
|
260
|
+
- `getVendors(relations)` - Retrieve all vendors
|
|
261
|
+
- `putVendor(id, data)` - Update a vendor
|
|
262
|
+
- `postVendor(data)` - Create a new vendor
|
|
263
|
+
|
|
264
|
+
#### Orders
|
|
265
|
+
|
|
266
|
+
- `getOrder(id, relations)` - Fetch a specific order by ID
|
|
267
|
+
- `getOrders(relations)` - Retrieve all orders
|
|
268
|
+
- `getOrdersByVendorID(id, relations)` - Get orders by vendor
|
|
269
|
+
- `getOpenOrdersByVendorID(id, relations)` - Get open orders by vendor
|
|
270
|
+
|
|
271
|
+
#### Sales
|
|
272
|
+
|
|
273
|
+
- `getSale(id, relations)` - Fetch a specific sale by ID
|
|
274
|
+
- `getSales(relations)` - Retrieve all sales
|
|
275
|
+
- `getMultipleSales(saleIDs, relations)` - Get multiple sales by IDs
|
|
276
|
+
- `getSalesByDateRange(startDate, endDate, relations)` - Get sales in date range
|
|
277
|
+
- `putSale(id, data)` - Update a sale
|
|
278
|
+
- `postSale(data)` - Create a new sale
|
|
279
|
+
|
|
280
|
+
#### Sale Lines
|
|
281
|
+
|
|
282
|
+
- `getSaleLinesByItem(itemID, relations)` - Get sale lines for an item
|
|
283
|
+
- `getSaleLinesByItems(ids, startDate, endDate, relations)` - Get sale lines for multiple items with date filter
|
|
284
|
+
- `getSaleLinesByVendorID(id, startDate, endDate, relations)` - Get sale lines by vendor with date filter
|
|
285
|
+
|
|
286
|
+
### Account & Configuration
|
|
287
|
+
|
|
288
|
+
#### Account Information
|
|
289
|
+
|
|
290
|
+
- `getAccount(relations)` - Get account/shop information
|
|
291
|
+
|
|
292
|
+
#### Employees
|
|
293
|
+
|
|
294
|
+
- `getEmployees(relations)` - Get all employees
|
|
295
|
+
- `getEmployee(id, relations)` - Get a specific employee
|
|
296
|
+
|
|
297
|
+
#### System Configuration
|
|
298
|
+
|
|
299
|
+
- `getCustomerTypes(relations)` - Get customer types
|
|
300
|
+
- `getRegisters(relations)` - Get registers/shops
|
|
301
|
+
- `getPaymentTypes(relations)` - Get payment types
|
|
302
|
+
- `getTaxClasses(relations)` - Get tax classes
|
|
303
|
+
- `getItemAttributes(relations)` - Get item attributes
|
|
304
|
+
|
|
305
|
+
### Gift Cards & Special Orders
|
|
306
|
+
|
|
307
|
+
- `getGiftCards(relations)` - Get all gift cards
|
|
308
|
+
- `getGiftCard(id, relations)` - Get a specific gift card by code
|
|
309
|
+
- `getSpecialOrders(relations)` - Get special orders
|
|
310
|
+
|
|
311
|
+
### Images
|
|
312
|
+
|
|
313
|
+
- `getImages(relations)` - Get all images
|
|
314
|
+
- `postImage(imageFilePath, metadata)` - Upload an image
|
|
315
|
+
|
|
316
|
+
### Utility Methods
|
|
317
|
+
|
|
318
|
+
- `ping()` - Test API connection and authentication
|
|
319
|
+
- `refreshTokens()` - Force refresh of access tokens
|
|
320
|
+
- `getTokenInfo()` - Get current token status information
|
|
321
|
+
|
|
322
|
+
## Error Handling
|
|
323
|
+
|
|
324
|
+
The SDK includes comprehensive error handling with automatic retries for transient failures:
|
|
325
|
+
|
|
326
|
+
```javascript
|
|
327
|
+
try {
|
|
328
|
+
const item = await api.getItem(123);
|
|
329
|
+
console.log(item);
|
|
330
|
+
} catch (error) {
|
|
331
|
+
console.error("API Error:", error.message);
|
|
332
|
+
// Error details are automatically logged by the SDK
|
|
333
|
+
}
|
|
46
334
|
```
|
|
47
335
|
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- `getOpenOrdersByVendorID(id, relations)`: Fetches all open orders for a specific vendor. Optionally, related data can be included.
|
|
66
|
-
- `getVendor(id, relations)`: Fetches a specific vendor by ID. Optionally, related data can be included.
|
|
67
|
-
- `getVendors(relations)`: Retrieves all vendors. Optionally, related data can be included.
|
|
68
|
-
- `getSale(id, relations)`: Fetches a specific sale by ID. Optionally, related data can be included.
|
|
69
|
-
- `getSales(relations)`: Retrieves all sales. Optionally, related data can be included.
|
|
70
|
-
- `getMultipleSales(saleIDs, relations)`: Fetches multiple sales by their IDs. Optionally, related data can be included.
|
|
71
|
-
- `getSaleLinesByItem(itemID, relations)`: Retrieves sale lines for a specific item. Optionally, related data can be included.
|
|
72
|
-
- `getSaleLinesByItems(ids, startDate, endDate, relations)`: Retrieves sale lines for multiple items, filtered by date range. Optionally, related data can be included.
|
|
73
|
-
- `getSaleLinesByVendorID(id, startDate, endDate, relations)`: Fetches sale lines for a specific vendor, filtered by date range. Optionally, related data can be included.
|
|
74
|
-
- `getSpecialOrders(relations)`: Fetches special orders. Optionally, related data can be included.
|
|
336
|
+
## Rate Limiting
|
|
337
|
+
|
|
338
|
+
The SDK automatically handles Lightspeed's API rate limits by:
|
|
339
|
+
|
|
340
|
+
- Monitoring rate limit headers
|
|
341
|
+
- Calculating appropriate delays
|
|
342
|
+
- Automatically waiting when limits are approached
|
|
343
|
+
|
|
344
|
+
## Pagination
|
|
345
|
+
|
|
346
|
+
For endpoints that return large datasets, the SDK automatically handles pagination:
|
|
347
|
+
|
|
348
|
+
```javascript
|
|
349
|
+
// This will automatically fetch all pages
|
|
350
|
+
const allItems = await api.getItems();
|
|
351
|
+
console.log(`Retrieved ${allItems.length} items`);
|
|
352
|
+
```
|
|
75
353
|
|
|
76
354
|
## Contributing
|
|
77
355
|
|
|
78
|
-
Contributions are welcome!
|
|
356
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
79
357
|
|
|
80
358
|
## License
|
|
81
359
|
|
|
@@ -87,4 +365,5 @@ This SDK is not officially affiliated with Lightspeed HQ and is provided "as is"
|
|
|
87
365
|
|
|
88
366
|
## More Info
|
|
89
367
|
|
|
90
|
-
|
|
368
|
+
- [Lightspeed Retail API Documentation](https://developers.lightspeedhq.com/retail/introduction/introduction/)
|
|
369
|
+
- [New OAuth Documentation](https://developers.lightspeedhq.com/retail/authentication/oauth/)
|