bc-api-client 0.1.0-beta.1 → 0.1.0-beta.10

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  <span style="color:orange">BETA VERSION - Use at your own risk</span>
4
4
 
5
- An opinionated and minimalistic client focusing on simplicity and performance.
5
+ An opinionated and minimalistic client focusing on simplicity and concurrent performance.
6
6
  Features (or antifeatures - depends on your opinion)
7
7
  - Node 20+ LTS, ESM
8
8
  - Bring Your Own Types
@@ -12,6 +12,19 @@ Features (or antifeatures - depends on your opinion)
12
12
  - Rate limit handling
13
13
  - App authenticator module. Request token and verify JWT.
14
14
 
15
+ ⚠️ **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.
16
+
17
+ ## Table of Contents
18
+ - [Installation](#installation)
19
+ - [Usage](#usage)
20
+ - [API Client](#api-client)
21
+ - [Authentication](#authentication)
22
+ - [API](#api)
23
+ - [BigCommerceClient](#bigcommerceclient)
24
+ - [BigCommerceAuth](#bigcommerceauth)
25
+ - [Tips](#tips)
26
+ - [License](#license)
27
+
15
28
  ## Installation
16
29
 
17
30
  ```bash
@@ -45,8 +58,7 @@ const client = new BigCommerceClient({
45
58
  });
46
59
 
47
60
  // Basic GET request
48
- const products = await client.get<V3Response<MyProduct[]>>({
49
- endpoint: bc.products.path,
61
+ const products = await client.get<V3Response<MyProduct[]>>(bc.products.path, {
50
62
  query: { 'include_fields': fields },
51
63
  });
52
64
 
@@ -63,8 +75,7 @@ const results = await client.concurrent<never, V3Response<MyProduct>>(
63
75
  );
64
76
 
65
77
  // Collect all pages from v3 endpoint
66
- const allProducts = await client.collect<MyProduct>({
67
- endpoint: bc.products.path,
78
+ const allProducts = await client.collect<MyProduct>(bc.products.path, {
68
79
  query: {
69
80
  include_fields: fields,
70
81
  },
@@ -78,8 +89,7 @@ type MyOrder = {
78
89
  status: string;
79
90
  }
80
91
 
81
- const orders = await client.collectV2<MyOrder>({
82
- endpoint: bc.orders.v2.path,
92
+ const orders = await client.collectV2<MyOrder>(bc.orders.v2.path, {
83
93
  query: {
84
94
  limit: '5',
85
95
  },
@@ -91,8 +101,7 @@ const orders = await client.collectV2<MyOrder>({
91
101
  // Note: productIds would be a large array of IDs in a real scenario
92
102
  const productIds = [1, 2, 3, 4, 5]; // Example IDs
93
103
 
94
- const filteredProducts = await client.query<MyProduct>({
95
- endpoint: bc.products.path,
104
+ const filteredProducts = await client.query<MyProduct>(bc.products.path, {
96
105
  key: 'id:in',
97
106
  values: productIds,
98
107
  query: {
@@ -112,60 +121,114 @@ const auth = new BigCommerceAuth({
112
121
  clientId: 'your-client-id',
113
122
  secret: 'your-client-secret',
114
123
  redirectUri: 'your-redirect-uri',
115
- storeHash: 'your-store-hash'
116
124
  });
117
125
 
118
126
  // Request token
119
127
  const token = await auth.requestToken(authQuery);
120
128
 
121
129
  // Verify JWT
122
- const claims = await auth.verify(jwtPayload);
130
+ const claims = await auth.verify(jwtPayload, 'your-store-hash');
123
131
  ```
124
132
 
125
133
  ## API
126
134
 
127
135
  ### BigCommerceClient
128
136
 
129
- #### `get<R>(options: GetOptions): Promise<R>`
137
+ #### Constructor
138
+ ```typescript
139
+ new BigCommerceClient(config: {
140
+ storeHash: string;
141
+ accessToken: string;
142
+ maxRetries?: number; // default: 5
143
+ maxDelay?: number; // default: 60000 (1 minute)
144
+ concurrency?: number; // default: 10
145
+ skipErrors?: boolean; // default: false
146
+ logger?: Logger; // optional
147
+ })
148
+ ```
149
+
150
+ #### `get<R>(endpoint: string, options?: GetOptions): Promise<R>`
130
151
  Makes a GET request to the BigCommerce API.
152
+ - `endpoint`: The API endpoint to request
153
+ - `options.query`: Query parameters to include in the request
154
+ - `options.version`: API version to use (v2 or v3, default: v3)
131
155
 
132
- #### `post<T, R>(options: PostOptions<T>): Promise<R>`
156
+ #### `post<T, R>(endpoint: string, options?: PostOptions<T>): Promise<R>`
133
157
  Makes a POST request to the BigCommerce API.
158
+ - `endpoint`: The API endpoint to request
159
+ - `options.query`: Query parameters to include in the request
160
+ - `options.version`: API version to use (v2 or v3, default: v3)
161
+ - `options.body`: Request body data of type `T`
134
162
 
135
- #### `put<T, R>(options: PostOptions<T>): Promise<R>`
163
+ #### `put<T, R>(endpoint: string, options?: PostOptions<T>): Promise<R>`
136
164
  Makes a PUT request to the BigCommerce API.
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`
137
169
 
138
- #### `delete<R>(endpoint: string): Promise<void>`
170
+ #### `delete<R>(endpoint: string, options?: Pick<GetOptions, 'version'>): Promise<void>`
139
171
  Makes a DELETE request to the BigCommerce API.
140
-
141
- #### `concurrent<T, R>(requests: RequestOptions<T>[], options: ConcurrencyOptions): Promise<R[]>`
142
- Executes multiple requests concurrently with rate limit handling. Options:
143
- - `concurrency`: number of concurrent requests (default: 10)
144
- - `skipErrors`: whether to skip failed requests instead of throwing (default: false)
145
-
146
- #### `collect<T>(options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>`
147
- Automatically fetches all pages of a paginated v3 endpoint. Supports the same concurrency options as `concurrent`.
148
-
149
- #### `collectV2<T>(options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>`
150
- Automatically fetches all pages of a paginated v2 endpoint. Supports the same concurrency options as `concurrent`.
151
-
152
- #### `query<T>(options: QueryOptions): Promise<T[]>`
153
- Executes a query with multiple filter values, automatically handling large value sets by chunking them into smaller requests. Options:
154
- - `endpoint`: API endpoint to query
155
- - `key`: Filter key (e.g. 'id:in')
156
- - `values`: Array of values to filter by
157
- - `query`: Additional query parameters
158
- - `concurrency`: number of concurrent requests (default: 10)
159
- - `skipErrors`: whether to skip failed requests instead of throwing (default: false)
172
+ - `endpoint`: The API endpoint to delete
173
+ - `options.version`: API version to use (v2 or v3, default: v3)
174
+
175
+ #### `concurrent<T, R>(requests: RequestOptions<T>[], options?: ConcurrencyOptions): Promise<R[]>`
176
+ Executes multiple requests concurrently with rate limit handling.
177
+ - `requests`: Array of request options to execute
178
+ - `options.concurrency`: Maximum number of concurrent requests (default: 10)
179
+ - `options.skipErrors`: Whether to skip errors and continue processing (default: false)
180
+
181
+ #### `collect<T>(endpoint: string, options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>`
182
+ Automatically fetches all pages of a paginated v3 endpoint. Pulls the first page and uses pagination meta to collect remaining pages concurrently.
183
+ - `endpoint`: The API endpoint to request
184
+ - `options.query`: Query parameters to include in the request (limit defaults to 250)
185
+ - `options.concurrency`: Maximum number of concurrent requests (default: 10)
186
+ - `options.skipErrors`: Whether to skip errors and continue processing (default: false)
187
+
188
+ #### `collectV2<T>(endpoint: string, options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>`
189
+ Automatically fetches all pages of a paginated v2 endpoint. Pulls all pages concurrently until a 204 is returned.
190
+ - `endpoint`: The API endpoint to request
191
+ - `options.query`: Query parameters to include in the request (limit defaults to 250)
192
+ - `options.concurrency`: Maximum number of concurrent requests (default: 10)
193
+ - `options.skipErrors`: Whether to skip errors and continue processing (default: false)
194
+
195
+ #### `query<T>(endpoint: string, options: QueryOptions): Promise<T[]>`
196
+ Queries multiple values against a single field using the v3 API. If the URL + query params are too long, the query will be chunked.
197
+ - `endpoint`: The API endpoint to request
198
+ - `options.key`: The field name to query against (e.g. 'id:in')
199
+ - `options.values`: Array of values to query for
200
+ - `options.query`: Additional query parameters (limit defaults to 250)
201
+ - `options.concurrency`: Maximum number of concurrent requests (default: 10)
202
+ - `options.skipErrors`: Whether to skip errors and continue processing (default: false)
160
203
 
161
204
  ### BigCommerceAuth
162
205
 
163
- #### `requestToken(data: string | AuthQuery): Promise<TokenResponse>`
206
+ #### Constructor
207
+ ```typescript
208
+ new BigCommerceAuth(config: {
209
+ clientId: string;
210
+ secret: string;
211
+ redirectUri: string;
212
+ scopes?: string[]; // optional
213
+ logger?: Logger; // optional
214
+ })
215
+ ```
216
+
217
+ #### `requestToken(data: string | UrlSearchParams | AuthQuery): Promise<TokenResponse>`
164
218
  Requests an access token from BigCommerce OAuth.
165
219
 
166
- #### `verify(jwtPayload: string): Promise<Claims>`
220
+ #### `verify(jwtPayload: string, storeHash: string): Promise<Claims>`
167
221
  Verifies a JWT payload from BigCommerce.
168
222
 
223
+ ## Tips
224
+
225
+ - 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.
226
+ - 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.
227
+ - 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.
228
+ - Use `query` if you need to fetch, for example, customers from a list of emails, or products from a list of SKUs.
229
+ - 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.
230
+ - 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.
231
+
169
232
  ## License
170
233
 
171
234
  MIT
package/dist/auth.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Logger } from './core';
1
2
  /**
2
3
  * Configuration options for BigCommerce authentication
3
4
  */
@@ -8,10 +9,10 @@ type Config = {
8
9
  secret: string;
9
10
  /** The redirect URI registered with BigCommerce */
10
11
  redirectUri: string;
11
- /** The store hash for the BigCommerce store */
12
- storeHash: string;
13
12
  /** Optional array of scopes to validate during auth callback */
14
13
  scopes?: string[];
14
+ /** Optional logger instance */
15
+ logger?: Logger;
15
16
  };
16
17
  /**
17
18
  * Query parameters received from BigCommerce auth callback
@@ -94,24 +95,30 @@ export type Claims = {
94
95
  export declare class BigCommerceAuth {
95
96
  private readonly config;
96
97
  /**
97
- * Creates a new BigCommerceAuth instance
98
+ * Creates a new BigCommerceAuth instance for handling OAuth authentication
98
99
  * @param config - Configuration options for BigCommerce authentication
100
+ * @param config.clientId - The OAuth client ID from BigCommerce
101
+ * @param config.secret - The OAuth client secret from BigCommerce
102
+ * @param config.redirectUri - The redirect URI registered with BigCommerce
103
+ * @param config.scopes - Optional array of scopes to validate during auth callback
104
+ * @param config.logger - Optional logger instance for debugging and error tracking
99
105
  * @throws {Error} If the redirect URI is invalid
100
106
  */
101
107
  constructor(config: Config);
102
108
  /**
103
109
  * Requests an access token from BigCommerce
104
- * @param data - Either a query string or AuthQuery object containing auth callback data
110
+ * @param data - Either a query string, URLSearchParams, or AuthQuery object containing auth callback data
105
111
  * @returns Promise resolving to the token response
106
112
  */
107
- requestToken(data: string | AuthQuery): Promise<TokenResponse>;
113
+ requestToken(data: string | AuthQuery | URLSearchParams): Promise<TokenResponse>;
108
114
  /**
109
115
  * Verifies a JWT payload from BigCommerce
110
116
  * @param jwtPayload - The JWT string to verify
117
+ * @param storeHash - The store hash for the BigCommerce store
111
118
  * @returns Promise resolving to the verified JWT claims
112
119
  * @throws {Error} If the JWT is invalid
113
120
  */
114
- verify(jwtPayload: string): Promise<Claims>;
121
+ verify(jwtPayload: string, storeHash: string): Promise<Claims>;
115
122
  /**
116
123
  * Parses and validates a query string from BigCommerce auth callback
117
124
  * @param queryString - The query string to parse
package/dist/client.d.ts CHANGED
@@ -1,30 +1,139 @@
1
+ import { Logger } from './core';
1
2
  import { RateLimitOptions, RequestOptions, StoreOptions } from './net';
3
+ /**
4
+ * Options for GET requests to the BigCommerce API
5
+ */
2
6
  export type GetOptions = {
3
- endpoint: string;
7
+ /** Query parameters to include in the request */
4
8
  query?: Record<string, string>;
9
+ /** API version to use (v2 or v3) */
5
10
  version?: 'v2' | 'v3';
6
11
  };
12
+ /**
13
+ * Options for POST/PUT requests to the BigCommerce API
14
+ */
7
15
  export type PostOptions<T> = GetOptions & {
16
+ /** Request body data */
8
17
  body: T;
9
18
  };
19
+ /**
20
+ * Options for controlling concurrent request behavior
21
+ */
10
22
  export type ConcurrencyOptions = {
23
+ /** Maximum number of concurrent requests (default: 10) */
11
24
  concurrency?: number;
25
+ /** Whether to skip errors and continue processing (default: false) */
12
26
  skipErrors?: boolean;
13
27
  };
28
+ /**
29
+ * Options for querying multiple values against a single filter field
30
+ */
14
31
  export type QueryOptions = Omit<GetOptions, 'version'> & ConcurrencyOptions & {
32
+ /** The field name to query against */
15
33
  key: string;
34
+ /** Array of values to query for */
16
35
  values: (string | number)[];
17
36
  };
18
- export type Config = StoreOptions & RateLimitOptions;
37
+ /**
38
+ * Configuration options for the BigCommerce client
39
+ */
40
+ export type Config = StoreOptions & RateLimitOptions & ConcurrencyOptions & {
41
+ /** Logger instance */
42
+ logger?: Logger;
43
+ };
44
+ /**
45
+ * Client for interacting with the BigCommerce API
46
+ *
47
+ * This client provides methods for making HTTP requests to the BigCommerce API,
48
+ * with support for both v2 and v3 endpoints, pagination, and concurrent requests.
49
+ */
19
50
  export declare class BigCommerceClient {
20
51
  private readonly config;
52
+ /**
53
+ * Creates a new BigCommerce client instance
54
+ * @param config - Configuration options for the client
55
+ * @param config.storeHash - The store hash to use for the client
56
+ * @param config.accessToken - The API access token to use for the client
57
+ * @param config.maxRetries - The maximum number of retries for rate limit errors (default: 5)
58
+ * @param config.maxDelay - Maximum time to wait to retry in case of rate limit errors in milliseconds (default: 60000 - 1 minute). If `X-Rate-Limit-Time-Reset-Ms` header is higher than `maxDelay`, the request will fail immediately.
59
+ * @param config.concurrency - The default concurrency for concurrent methods (default: 10)
60
+ * @param config.skipErrors - Whether to skip errors during concurrent requests (default: false)
61
+ * @param config.logger - Optional logger instance for debugging and error tracking
62
+ */
21
63
  constructor(config: Config);
22
- get<R>(options: GetOptions): Promise<R>;
23
- post<T, R>(options: PostOptions<T>): Promise<R>;
24
- put<T, R>(options: PostOptions<T>): Promise<R>;
25
- delete<R>(endpoint: string): Promise<void>;
26
- concurrent<T, R>(requests: RequestOptions<T>[], options: ConcurrencyOptions): Promise<R[]>;
27
- collect<T>(options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>;
28
- collectV2<T>(options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>;
29
- query<T>(options: QueryOptions): Promise<T[]>;
64
+ /**
65
+ * Makes a GET request to the BigCommerce API
66
+ * @param endpoint - The API endpoint to request
67
+ * @param options.query - Query parameters to include in the request
68
+ * @param options.version - API version to use (v2 or v3) (default: v3)
69
+ * @returns Promise resolving to the response data of type `R`
70
+ */
71
+ get<R>(endpoint: string, options?: GetOptions): Promise<R>;
72
+ /**
73
+ * Makes a POST request to the BigCommerce API
74
+ * @param endpoint - The API endpoint to request
75
+ * @param options.query - Query parameters to include in the request
76
+ * @param options.version - API version to use (v2 or v3) (default: v3)
77
+ * @param options.body - Request body data of type `T`
78
+ * @returns Promise resolving to the response data of type `R`
79
+ */
80
+ post<T, R>(endpoint: string, options?: PostOptions<T>): Promise<R>;
81
+ /**
82
+ * Makes a PUT request to the BigCommerce API
83
+ * @param endpoint - The API endpoint to request
84
+ * @param options.query - Query parameters to include in the request
85
+ * @param options.version - API version to use (v2 or v3) (default: v3)
86
+ * @param options.body - Request body data of type `T`
87
+ * @returns Promise resolving to the response data of type `R`
88
+ */
89
+ put<T, R>(endpoint: string, options?: PostOptions<T>): Promise<R>;
90
+ /**
91
+ * Makes a DELETE request to the BigCommerce API
92
+ * @param endpoint - The API endpoint to delete
93
+ * @param options.version - API version to use (v2 or v3) (default: v3)
94
+ * @returns Promise resolving to void
95
+ */
96
+ delete<R>(endpoint: string, options?: Pick<GetOptions, 'version'>): Promise<void>;
97
+ /**
98
+ * Executes multiple requests concurrently with controlled concurrency
99
+ * @param requests - Array of request options to execute
100
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
101
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
102
+ * @returns Promise resolving to array of response data
103
+ */
104
+ concurrent<T, R>(requests: RequestOptions<T>[], options?: ConcurrencyOptions): Promise<R[]>;
105
+ /**
106
+ * Collects all pages of data from a paginated v3 API endpoint.
107
+ * This method pulls the first page and uses pagination meta to collect the remaining pages concurrently.
108
+ * @param endpoint - The API endpoint to request
109
+ * @param options.query - Query parameters to include in the request
110
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
111
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
112
+ * @returns Promise resolving to array of all items across all pages
113
+ */
114
+ collect<T>(endpoint: string, options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>;
115
+ /**
116
+ * Collects all pages of data from a paginated v2 API endpoint.
117
+ * This method simply pulls all pages concurrently until a 204 is returned in a batch.
118
+ * @param endpoint - The API endpoint to request
119
+ * @param options.query - Query parameters to include in the request
120
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
121
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
122
+ * @returns Promise resolving to array of all items across all pages
123
+ */
124
+ collectV2<T>(endpoint: string, options: Omit<GetOptions, 'version'> & ConcurrencyOptions): Promise<T[]>;
125
+ /**
126
+ * Queries multiple values against a single field using the v3 API.
127
+ * If the url + query params are too long, the query will be chunked. Otherwise, this method acts like `collect`.
128
+ * This method does not check for uniqueness of the `values` array.
129
+ *
130
+ * @param endpoint - The API endpoint to request
131
+ * @param options.key - The field name to query against e.g. `sku:in`
132
+ * @param options.values - Array of values to query for e.g. `['123', '456', ...]`
133
+ * @param options.query - Additional query parameters
134
+ * @param options.concurrency - Maximum number of concurrent requests, overrides the client's concurrency setting (default: 10)
135
+ * @param options.skipErrors - Whether to skip errors and continue processing, overrides the client's skipErrors setting (default: false)
136
+ * @returns Promise resolving to array of matching items
137
+ */
138
+ query<T>(endpoint: string, options: QueryOptions): Promise<T[]>;
30
139
  }
package/dist/core.d.ts CHANGED
@@ -16,3 +16,12 @@ export type V3Resource<T> = {
16
16
  pagination: Pagination;
17
17
  };
18
18
  };
19
+ /**
20
+ * Logger interface for logging messages and data, Pino compatible by default
21
+ */
22
+ export interface Logger {
23
+ debug: (data: unknown, message?: string) => void;
24
+ info: (data: unknown, message?: string) => void;
25
+ warn: (data: unknown, message?: string) => void;
26
+ error: (data: unknown, message?: string) => void;
27
+ }