bc-api-client 0.2.2 → 1.0.0-beta.2

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,262 +1,124 @@
1
1
  # Bigcommerce management API client and JWT authenticator
2
2
 
3
- <span style="color:orange">BETA VERSION - Use at your own risk</span>
3
+ [![CI](https://github.com/kernelpanic99/bc-api-client/actions/workflows/ci.yml/badge.svg)](https://github.com/kernelpanic99/bc-api-client/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/bc-api-client/beta)](https://www.npmjs.com/package/bc-api-client?activeTab=versions)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+ [![Node 22+](https://img.shields.io/badge/node-22%2B-brightgreen)](https://nodejs.org)
4
7
 
5
- An opinionated and minimalistic client focusing on simplicity and concurrent performance.
6
- Features (or antifeatures - depends on your opinion)
7
-
8
- - Node 20+ LTS, ESM
9
- - Bring Your Own Types
10
- - Basic API methods (get, post, put, delete)
11
- - Advanced methods for concurrent querying and fetching
12
- - All methods are generic
13
- - Rate limit handling
14
- - App authenticator module. Request token and verify JWT.
8
+ > [!WARNING]
9
+ > V1 is a complete rewrite. See [Migration Guide](docs/V1_MIGRATION_GUIDE.md)
15
10
 
16
- ⚠️ **Disclaimer**: This library provides concurrent request capabilities. BigCommerce has strict rate limits that vary by plan and endpoint. The author is not responsible for any issues arising from improper API usage. Use at your own risk.
11
+ An opinionated and minimalistic client focusing on simplicity and concurrent performance.
17
12
 
18
13
  ## Table of Contents
19
14
 
20
15
  - [Installation](#installation)
21
16
  - [Usage](#usage)
22
- - [API Client](#api-client)
23
- - [Authentication](#authentication)
24
- - [API](#api)
25
- - [BigCommerceClient](#bigcommerceclient)
26
- - [BigCommerceAuth](#bigcommerceauth)
17
+ - [API Client](#api-client)
18
+ - [Authentication](#authentication)
19
+ - [API Reference](#api-reference)
20
+ - [BigCommerceClient](#bigcommerceclient)
21
+ - [BigCommerceAuth](#bigcommerceauth)
27
22
  - [Tips](#tips)
28
23
  - [License](#license)
29
24
 
25
+ ## Features
26
+
27
+ - Node 22+, ESM only
28
+ - Built-in [Standard Schema](https://standardschema.dev/) validation support
29
+ - Basic API methods (get, post, put, delete)
30
+ - Rate limit handling and retries on transient errors
31
+ - High-performance concurrency utilities:
32
+ - Async generator streams
33
+ - Automatic concurrency backoff on 429 and 5xx
34
+ - V3 envelope pagination
35
+ - V2 "blind" pagination until 404, 204 or a given page limit
36
+ - App authenticator module. Request token and verify JWT.
37
+
30
38
  ## Installation
31
39
 
32
40
  ```bash
33
- npm install bc-api-client
41
+ npm install bc-api-client@beta
34
42
  # or
35
- pnpm add bc-api-client
43
+ pnpm add bc-api-client@beta
36
44
  # or
37
- yarn add bc-api-client
45
+ yarn add bc-api-client@beta
38
46
  ```
39
47
 
40
48
  ## Usage
41
49
 
50
+ See the [full usage guide](docs/USAGE.md) for all methods and options.
51
+
42
52
  ### API Client
43
53
 
44
54
  ```typescript
45
- import { BigCommerceClient, V3Response } from 'bigcommerce-client';
46
- import { bc } from 'bigcommerce-client/endpoints';
47
-
48
- type MyProduct = {
49
- id: number;
50
- name: string;
51
- sku: string;
52
- inventory_level: number;
53
- };
55
+ import { BigCommerceClient } from "bc-api-client";
56
+ import z from "zod";
57
+
58
+ // Using zod as the most popular one, but any validator supporting [StandardSchema](https://standardschema.dev/) will work
59
+ const productSchema = z.object({
60
+ id: z.int().positive(),
61
+ name: z.string(),
62
+ sku: z.string(),
63
+ inventory_level: z.int().nonnegative(),
64
+ });
54
65
 
55
- const fields = 'id,name,sku,inventory_level';
66
+ const fields = Object.keys(productSchema.shape);
56
67
 
57
68
  const client = new BigCommerceClient({
58
- storeHash: 'your-store-hash',
59
- accessToken: 'your-access-token',
69
+ storeHash: "your-store-hash",
70
+ accessToken: "your-access-token",
60
71
  });
61
72
 
62
- // Basic GET request
63
- const products = await client.get<V3Response<MyProduct[]>>(bc.products.path, {
73
+ // Basic GET request — response is typed automatically
74
+ const { data: product } = await client.get("/catalog/products/123", {
75
+ responseSchema: z.object({ data: productSchema }),
64
76
  query: { include_fields: fields },
65
77
  });
66
78
 
67
- // Low level concurrent requests with error handling
68
- const results = await client.concurrent<never, V3Response<MyProduct>>(
69
- [
70
- { method: 'GET', endpoint: bc.products.byId(1), query: { include_fields: fields } },
71
- { method: 'GET', endpoint: bc.products.byId(2), query: { include_fields: fields } },
72
- ],
73
- {
74
- concurrency: 10,
75
- skipErrors: true, // Optional: skip failed requests instead of throwing
76
- },
77
- );
78
-
79
- // Collect all pages from v3 endpoint
80
- const allProducts = await client.collect<MyProduct>(bc.products.path, {
81
- query: {
82
- include_fields: fields,
83
- },
84
- concurrency: 10, // Optional: control concurrent requests
85
- skipErrors: true, // Optional: skip failed requests
86
- });
87
-
88
- // Collect all pages from v2 endpoint
89
- type MyOrder = {
90
- id: number;
91
- status: string;
92
- };
93
-
94
- const orders = await client.collectV2<MyOrder>(bc.orders.v2.path, {
95
- query: {
96
- limit: '5',
97
- },
98
- concurrency: 10, // Optional: control concurrent requests
99
- skipErrors: true, // Optional: skip failed requests
100
- });
101
-
102
- // Query with multiple filter values
103
- // Note: productIds would be a large array of IDs in a real scenario
104
- const productIds = [1, 2, 3, 4, 5]; // Example IDs
105
-
106
- const filteredProducts = await client.query<MyProduct>(bc.products.path, {
107
- key: 'id:in',
108
- values: productIds,
109
- query: {
110
- include_fields: fields,
111
- },
112
- concurrency: 10, // Optional: control concurrent requests
113
- skipErrors: true, // Optional: skip failed requests
114
- });
79
+ console.log(`Got product: ${product.name}`);
80
+
81
+ // Paginate v3 collection concurrently with async generator
82
+ for await (const { err, data: product } of client.stream("/catalog/products", {
83
+ itemSchema: productSchema,
84
+ })) {
85
+ if (err) {
86
+ console.error("Something went wrong", err);
87
+ } else {
88
+ console.log(`Fetched product: ${product.name}`);
89
+ }
90
+ }
115
91
  ```
116
92
 
117
93
  ### Authentication
118
94
 
119
95
  ```typescript
120
- import { BigCommerceAuth } from 'bigcommerce-client';
96
+ import { BigCommerceAuth } from "bc-api-client";
121
97
 
122
98
  const auth = new BigCommerceAuth({
123
- clientId: 'your-client-id',
124
- secret: 'your-client-secret',
125
- redirectUri: 'your-redirect-uri',
99
+ clientId: "your-client-id",
100
+ secret: "your-client-secret",
101
+ redirectUri: "your-redirect-uri",
126
102
  });
127
103
 
128
104
  // Request token
129
105
  const token = await auth.requestToken(authQuery);
130
106
 
131
107
  // Verify JWT
132
- const claims = await auth.verify(jwtPayload, 'your-store-hash');
133
- ```
134
-
135
- ## API
136
-
137
- ### BigCommerceClient
138
-
139
- #### Constructor
140
-
141
- ```typescript
142
- new BigCommerceClient(config: {
143
- storeHash: string;
144
- accessToken: string;
145
- maxRetries?: number; // default: 5
146
- maxDelay?: number; // default: 60000 (1 minute)
147
- concurrency?: number; // default: 10
148
- skipErrors?: boolean; // default: false
149
- logger?: Logger; // optional
150
- })
151
- ```
152
-
153
- #### `get<R>(endpoint: string, options?: GetOptions): Promise<R>`
154
-
155
- Makes a GET request to the BigCommerce API.
156
-
157
- - `endpoint`: The API endpoint to request
158
- - `options.query`: Query parameters to include in the request
159
- - `options.version`: API version to use (v2 or v3, default: v3)
160
-
161
- #### `post<T, R>(endpoint: string, options?: PostOptions<T>): Promise<R>`
162
-
163
- Makes a POST request to the BigCommerce API.
164
-
165
- - `endpoint`: The API endpoint to request
166
- - `options.query`: Query parameters to include in the request
167
- - `options.version`: API version to use (v2 or v3, default: v3)
168
- - `options.body`: Request body data of type `T`
169
-
170
- #### `put<T, R>(endpoint: string, options?: PostOptions<T>): Promise<R>`
171
-
172
- Makes a PUT request to the BigCommerce API.
173
-
174
- - `endpoint`: The API endpoint to request
175
- - `options.query`: Query parameters to include in the request
176
- - `options.version`: API version to use (v2 or v3, default: v3)
177
- - `options.body`: Request body data of type `T`
178
-
179
- #### `delete<R>(endpoint: string, options?: Pick<GetOptions, 'version'>): Promise<void>`
180
-
181
- Makes a DELETE request to the BigCommerce API.
182
-
183
- - `endpoint`: The API endpoint to delete
184
- - `options.version`: API version to use (v2 or v3, default: v3)
185
-
186
- #### `concurrent<T, R>(requests: RequestOptions<T>[], options?: ConcurrencyOptions): Promise<R[]>`
187
-
188
- Executes multiple requests concurrently with rate limit handling.
189
-
190
- - `requests`: Array of request options to execute
191
- - `options.concurrency`: Maximum number of concurrent requests (default: 10)
192
- - `options.skipErrors`: Whether to skip errors and continue processing (the errors will be logged if logger is provided), default: false)
193
-
194
- #### `concurrentSettled<T, R>(requests: RequestOptions<T>[], options?: Pick<ConcurrencyOptions, 'concurrency'>): Promise<PromiseSettledResult<R>[]>`
195
-
196
- Lowest level concurrent request method. This method executes requests in chunks and returns bare PromiseSettledResult objects. Use this method if you need to handle errors in a custom way.
197
-
198
- - `requests`: Array of request options to execute
199
- - `options.concurrency`: Maximum number of concurrent requests (default: 10)
200
-
201
- #### `collect<T>(endpoint: string, options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>`
202
-
203
- Automatically fetches all pages of a paginated v3 endpoint. Pulls the first page and uses pagination meta to collect remaining pages concurrently.
204
-
205
- - `endpoint`: The API endpoint to request
206
- - `options.query`: Query parameters to include in the request (limit defaults to 250)
207
- - `options.concurrency`: Maximum number of concurrent requests (default: 10)
208
- - `options.skipErrors`: Whether to skip errors and continue processing (default: false)
209
-
210
- #### `collectV2<T>(endpoint: string, options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>`
211
-
212
- Automatically fetches all pages of a paginated v2 endpoint. Pulls all pages concurrently until a 204 is returned.
213
-
214
- - `endpoint`: The API endpoint to request
215
- - `options.query`: Query parameters to include in the request (limit defaults to 250)
216
- - `options.concurrency`: Maximum number of concurrent requests (default: 10)
217
- - `options.skipErrors`: Whether to skip errors and continue processing (default: false)
218
-
219
- #### `query<T>(endpoint: string, options: QueryOptions): Promise<T[]>`
220
-
221
- Queries multiple values against a single field using the v3 API. If the URL + query params are too long, the query will be chunked.
222
-
223
- - `endpoint`: The API endpoint to request
224
- - `options.key`: The field name to query against (e.g. 'id:in')
225
- - `options.values`: Array of values to query for
226
- - `options.query`: Additional query parameters (limit defaults to 250)
227
- - `options.concurrency`: Maximum number of concurrent requests (default: 10)
228
- - `options.skipErrors`: Whether to skip errors and continue processing (default: false)
229
-
230
- ### BigCommerceAuth
231
-
232
- #### Constructor
233
-
234
- ```typescript
235
- new BigCommerceAuth(config: {
236
- clientId: string;
237
- secret: string;
238
- redirectUri: string;
239
- scopes?: string[]; // optional
240
- logger?: Logger; // optional
241
- })
108
+ const claims = await auth.verify(jwtPayload, "your-store-hash");
242
109
  ```
243
110
 
244
- #### `requestToken(data: string | UrlSearchParams | AuthQuery): Promise<TokenResponse>`
245
-
246
- Requests an access token from BigCommerce OAuth.
247
-
248
- #### `verify(jwtPayload: string, storeHash: string): Promise<Claims>`
111
+ ## API Reference
249
112
 
250
- Verifies a JWT payload from BigCommerce.
113
+ - [BigCommerceClient](/docs/api/classes/BigCommerceClient.md)
114
+ - [BigCommerceAuth](/docs/api/classes/BigCommerceAuth.md)
251
115
 
252
116
  ## Tips
253
117
 
254
- - I made this library based on my experience of building real-time integrations. It might not be the best choice if you just need to make simple requests or want built-in types. Also, if you're not on enterprise - you can't realistically get much benefit from concurrency, so this library can offer zero to negative (getting throttled) benefit. Check out [this client](https://github.com/kzhang-dsg/bigcommerce-api-client) for a more extensive solution with much better DX. You can also use that library as a source of types and this one for concurrency if you don't mind having two installed.
255
- - Be careful with concurrent methods as they might get you flagged, especially if you are not working with enterprise stores (which I mostly do). Also, some endpoints have explicit concurrency limits. Check the documentation.
256
- - Utilize `include_fields` when available and make simplified types to include only the properties you need. This will increase the speed and efficiency of the requests significantly and improve DX as your autocomplete won't be cluttered.
257
- - Use `query` if you need to fetch, for example, customers from a list of emails, or products from a list of SKUs.
258
- - This library will not wait for a rate limit longer than 60 seconds by default. I mostly work on real-time applications, so it doesn't make sense to wait longer for me. If you need a longer timeout, pass `maxDelay` to the `BigCommerceClient` constructor.
259
- - Be careful with endpoints. I populated them manually from the docs and ran them through Claude as a double-check. You can make an issue if something throws a 404, and use the string meanwhile. Also, some may be missing - always check the documentation for your request.
118
+ - This library is built for real-time integrations on enterprise stores. If you're on a lower-tier plan, concurrency can do more harm than good (throttling). Note that some endpoints have explicit concurrency limits; always check the BC docs. **Use at your own risk.**
119
+ - Utilize `include_fields` when available and define simplified schemas with only the fields you need. This significantly improves request speed and keeps autocomplete clean.
120
+ - Use `query` to fetch resources by a large list of values, e.g. products by a list of IDs or customers by a list of emails. It works around the max URL size limitation.
121
+ - By default, the client will not wait more than 120 seconds for a rate limit to reset. For longer waits, pass `retry: { maxRetryAfter: <ms> }` to the constructor.
260
122
 
261
123
  ## License
262
124