@bundleup/sdk 0.0.16 → 0.0.18

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,4 +1,335 @@
1
- # Official Bundle Up SDK Library
1
+ # BundleUp JavaScript SDK
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@bundleup/sdk.svg)](https://www.npmjs.com/package/@bundleup/sdk)
4
- [![Documentation](https://img.shields.io/badge/documentation-bundleup.io-green.svg)](https://bundleup.io/docs/sdk)
4
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
5
+
6
+ Official JavaScript/TypeScript SDK for the [BundleUp](https://bundleup.io) API. Connect to 100+ integrations with a single, unified API.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @bundleup/sdk
12
+ ```
13
+
14
+ Or with yarn:
15
+
16
+ ```bash
17
+ yarn add @bundleup/sdk
18
+ ```
19
+
20
+ Or with pnpm:
21
+
22
+ ```bash
23
+ pnpm add @bundleup/sdk
24
+ ```
25
+
26
+ ## Requirements
27
+
28
+ - Node.js 16 or higher
29
+ - TypeScript 5.0+ (for TypeScript projects)
30
+
31
+ ## Features
32
+
33
+ - **TypeScript First** - Built with TypeScript, includes full type definitions
34
+ - **Modern JavaScript** - ESM and CommonJS support for maximum compatibility
35
+ - **Promise-based API** - Uses native fetch for all HTTP requests
36
+ - **Comprehensive Coverage** - Full support for Connections, Integrations, Webhooks, Proxy, and Unify APIs
37
+ - **Lightweight** - Zero dependencies beyond native fetch API
38
+
39
+ ## Quick Start
40
+
41
+ ```javascript
42
+ import { BundleUp } from '@bundleup/sdk';
43
+
44
+ // Initialize the client with your API key
45
+ const client = new BundleUp(process.env.BUNDLEUP_API_KEY);
46
+
47
+ // List all connections
48
+ const connections = await client.connections.list();
49
+ console.log(connections);
50
+ ```
51
+
52
+ ## Authentication
53
+
54
+ The BundleUp SDK uses API keys for authentication. You can obtain your API key from the [BundleUp Dashboard](https://app.bundleup.io).
55
+
56
+ ```javascript
57
+ import { BundleUp } from '@bundleup/sdk';
58
+
59
+ // Initialize with API key
60
+ const client = new BundleUp('your_api_key_here');
61
+
62
+ // Or use environment variable (recommended)
63
+ const client = new BundleUp(process.env.BUNDLEUP_API_KEY);
64
+ ```
65
+
66
+ **Security Best Practice:** Never commit your API keys to version control. Use environment variables or a secure credential management system.
67
+
68
+ ## Usage
69
+
70
+ ### Connections
71
+
72
+ Manage your integration connections:
73
+
74
+ ```javascript
75
+ // List all connections
76
+ const connections = await client.connections.list();
77
+
78
+ // List with query parameters
79
+ const connections = await client.connections.list({ status: 'active', limit: '10' });
80
+
81
+ // Retrieve a specific connection
82
+ const connection = await client.connections.retrieve('conn_123');
83
+
84
+ // Delete a connection
85
+ await client.connections.del('conn_123');
86
+ ```
87
+
88
+ ### Integrations
89
+
90
+ Work with available integrations:
91
+
92
+ ```javascript
93
+ // List all integrations
94
+ const integrations = await client.integrations.list();
95
+
96
+ // Retrieve a specific integration
97
+ const integration = await client.integrations.retrieve('int_123');
98
+ ```
99
+
100
+ ### Webhooks
101
+
102
+ Manage webhook subscriptions:
103
+
104
+ ```javascript
105
+ // List all webhooks
106
+ const webhooks = await client.webhooks.list();
107
+
108
+ // Create a webhook
109
+ const webhook = await client.webhooks.create({
110
+ url: 'https://example.com/webhook',
111
+ events: {
112
+ 'connection.created': true,
113
+ 'connection.deleted': true
114
+ }
115
+ });
116
+
117
+ // Retrieve a webhook
118
+ const webhook = await client.webhooks.retrieve('webhook_123');
119
+
120
+ // Update a webhook
121
+ const updated = await client.webhooks.update('webhook_123', {
122
+ url: 'https://example.com/new-webhook'
123
+ });
124
+
125
+ // Delete a webhook
126
+ await client.webhooks.del('webhook_123');
127
+ ```
128
+
129
+ ### Proxy API
130
+
131
+ Make direct calls to the underlying integration APIs:
132
+
133
+ ```javascript
134
+ // Create a proxy instance
135
+ const proxy = client.proxy('conn_123');
136
+
137
+ // Make GET request
138
+ const users = await proxy.get('/api/users');
139
+ const data = await users.json();
140
+
141
+ // Make POST request
142
+ const response = await proxy.post('/api/users', JSON.stringify({
143
+ name: 'John Doe',
144
+ email: 'john@example.com'
145
+ }));
146
+ const newUser = await response.json();
147
+
148
+ // Make PUT request
149
+ const response = await proxy.put('/api/users/123', JSON.stringify({
150
+ name: 'Jane Doe'
151
+ }));
152
+
153
+ // Make PATCH request
154
+ const response = await proxy.patch('/api/users/123', JSON.stringify({
155
+ email: 'jane@example.com'
156
+ }));
157
+
158
+ // Make DELETE request
159
+ await proxy.delete('/api/users/123');
160
+ ```
161
+
162
+ ### Unify API
163
+
164
+ Access unified, normalized data across different integrations.
165
+
166
+ #### Chat (Slack, Discord, Microsoft Teams, etc.)
167
+
168
+ ```javascript
169
+ // Get unified API instance for a connection
170
+ const unify = client.unify('conn_123');
171
+
172
+ // List channels
173
+ const channels = await unify.chat.channels({ limit: 100 });
174
+
175
+ // List channels with pagination
176
+ const channels = await unify.chat.channels({
177
+ limit: 50,
178
+ after: 'cursor_token'
179
+ });
180
+
181
+ // Include raw response from the integration
182
+ const channels = await unify.chat.channels({
183
+ limit: 100,
184
+ includeRaw: true
185
+ });
186
+ ```
187
+
188
+ #### Git (GitHub, GitLab, Bitbucket, etc.)
189
+
190
+ ```javascript
191
+ const unify = client.unify('conn_123');
192
+
193
+ // List repositories
194
+ const repos = await unify.git.repos({ limit: 50 });
195
+
196
+ // List pull requests for a repository
197
+ const pulls = await unify.git.pulls({
198
+ repoName: 'owner/repo',
199
+ limit: 20
200
+ });
201
+
202
+ // List tags for a repository
203
+ const tags = await unify.git.tags({ repoName: 'owner/repo' });
204
+
205
+ // List releases for a repository
206
+ const releases = await unify.git.releases({
207
+ repoName: 'owner/repo',
208
+ limit: 10
209
+ });
210
+
211
+ // Include raw response
212
+ const repos = await unify.git.repos({ includeRaw: true });
213
+ ```
214
+
215
+ #### Project Management (Jira, Linear, Asana, etc.)
216
+
217
+ ```javascript
218
+ // Get issues
219
+ const issues = await client.unify('conn_123').pm.issues({ limit: 100 });
220
+
221
+ // List with pagination
222
+ const issues = await client.unify('conn_123').pm.issues({
223
+ limit: 50,
224
+ after: 'cursor_token'
225
+ });
226
+
227
+ // Include raw response
228
+ const issues = await client.unify('conn_123').pm.issues({
229
+ includeRaw: true
230
+ });
231
+ ```
232
+
233
+ ## Error Handling
234
+
235
+ The SDK throws standard JavaScript errors. You can catch and handle them as needed:
236
+
237
+ ```javascript
238
+ try {
239
+ const client = new BundleUp('your-api-key');
240
+ const connections = await client.connections.list();
241
+ } catch (error) {
242
+ if (error.message.includes('401')) {
243
+ console.error('Authentication failed: Invalid API key');
244
+ } else if (error.message.includes('404')) {
245
+ console.error('Resource not found');
246
+ } else if (error.message.includes('429')) {
247
+ console.error('Rate limit exceeded');
248
+ } else {
249
+ console.error('API error:', error.message);
250
+ }
251
+ }
252
+ ```
253
+
254
+ ## Advanced Usage
255
+
256
+ ### Query Parameters
257
+
258
+ The `list()` method supports query parameters:
259
+
260
+ ```javascript
261
+ // List with filters
262
+ const connections = await client.connections.list({
263
+ status: 'active',
264
+ limit: '50',
265
+ page: '1'
266
+ });
267
+ ```
268
+
269
+ ### Custom Headers
270
+
271
+ When using the Proxy API, you can pass custom headers:
272
+
273
+ ```javascript
274
+ const proxy = client.proxy('conn_123');
275
+ const response = await proxy.get('/api/users', {}, {
276
+ 'X-Custom-Header': 'value'
277
+ });
278
+ ```
279
+
280
+ ### TypeScript Support
281
+
282
+ The SDK is written in TypeScript and includes comprehensive type definitions:
283
+
284
+ ```typescript
285
+ import { BundleUp } from '@bundleup/sdk';
286
+
287
+ const client = new BundleUp(process.env.BUNDLEUP_API_KEY!);
288
+
289
+ // Types are inferred automatically
290
+ const connections = await client.connections.list();
291
+ const webhook = await client.webhooks.create({
292
+ url: 'https://example.com/webhook',
293
+ events: {
294
+ 'connection.created': true
295
+ }
296
+ });
297
+ ```
298
+
299
+ ## Development
300
+
301
+ After cloning the repository, install dependencies:
302
+
303
+ ```bash
304
+ npm install
305
+ ```
306
+
307
+ Build the package:
308
+
309
+ ```bash
310
+ npm run build
311
+ ```
312
+
313
+ Run tests:
314
+
315
+ ```bash
316
+ npm test
317
+ ```
318
+
319
+ ## Contributing
320
+
321
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bundleup/javascript.
322
+
323
+ ## License
324
+
325
+ This package is available as open source under the terms of the [ISC License](https://opensource.org/licenses/ISC).
326
+
327
+ ## Support
328
+
329
+ - Documentation: [https://docs.bundleup.io](https://docs.bundleup.io)
330
+ - Email: [support@bundleup.io](mailto:support@bundleup.io)
331
+ - GitHub Issues: [https://github.com/bundleup/javascript/issues](https://github.com/bundleup/javascript/issues)
332
+
333
+ ## Code of Conduct
334
+
335
+ Everyone interacting in the BundleUp project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bundleup/javascript/blob/main/CODE_OF_CONDUCT).
package/dist/index.d.mts CHANGED
@@ -4,7 +4,7 @@ declare abstract class Base$1<T> {
4
4
  private baseUrl;
5
5
  private version;
6
6
  constructor(apiKey: string);
7
- protected buildUrl(path?: string | null, searchParams?: Record<string, any>): URL;
7
+ protected buildUrl(path?: string | null, searchParams?: Record<string, string>): URL;
8
8
  protected get headers(): Record<string, string>;
9
9
  /**
10
10
  * List resources with optional query parameters.
@@ -12,14 +12,14 @@ declare abstract class Base$1<T> {
12
12
  * @returns A promise that resolves to an array of resources.
13
13
  * @throws If params is not an object or if the fetch request fails.
14
14
  */
15
- list<K extends Record<string, any>>(searchParams?: K): Promise<T[]>;
15
+ list<K extends Record<string, string>>(searchParams?: K): Promise<T[]>;
16
16
  /**
17
17
  * Create a new resource.
18
18
  * @param body - The request body containing resource details.
19
19
  * @returns A promise that resolves to the created resource.
20
20
  * @throws If body is not an object or if the fetch request fails.
21
21
  */
22
- create<K extends Record<string, any>>(body: K): Promise<T>;
22
+ create<K extends Record<string, unknown>>(body: K): Promise<T>;
23
23
  /**
24
24
  * Retrieve a specific resource by ID.
25
25
  * @param id - The ID of the resource to retrieve.
@@ -34,7 +34,7 @@ declare abstract class Base$1<T> {
34
34
  * @returns A promise that resolves to the updated resource.
35
35
  * @throws If id is not provided, if body is not an object, or if the fetch request fails.
36
36
  */
37
- update<K extends Record<string, any>>(id: string, body: K): Promise<T>;
37
+ update<K extends Record<string, unknown>>(id: string, body: K): Promise<T>;
38
38
  /**
39
39
  * Delete a specific resource by ID.
40
40
  * @param id - The ID of the resource to delete.
@@ -88,38 +88,13 @@ declare class Proxy {
88
88
  private get headers();
89
89
  constructor(apiKey: string, connectionId: string);
90
90
  private buildUrl;
91
- get(path: string, searchParams?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
92
- post(path: string, body?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
93
- put(path: string, body?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
94
- patch(path: string, body?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
91
+ get(path: string, headers?: Record<string, string>): Promise<Response>;
92
+ post(path: string, body: BodyInit, headers?: Record<string, string>): Promise<Response>;
93
+ put(path: string, body: BodyInit, headers?: Record<string, string>): Promise<Response>;
94
+ patch(path: string, body: BodyInit, headers?: Record<string, string>): Promise<Response>;
95
95
  delete(path: string, headers?: Record<string, string>): Promise<Response>;
96
96
  }
97
97
 
98
- interface SessionCreateRequest {
99
- integrationId: string;
100
- externalId?: string;
101
- metadata?: Record<string, any>;
102
- redirectUri?: string;
103
- }
104
- interface SessionCreateResponse {
105
- token: string;
106
- auth_url: string;
107
- expires_in: number;
108
- external_id?: string;
109
- }
110
- declare class Sessions {
111
- private apiKey;
112
- constructor(apiKey: string);
113
- private get headers();
114
- /**
115
- * Create a new session.
116
- * @param params - The session creation parameters.
117
- * @returns A promise that resolves to the created session details.
118
- * @throws If the fetch request fails.
119
- */
120
- create(params: SessionCreateRequest): Promise<SessionCreateResponse>;
121
- }
122
-
123
98
  interface Params {
124
99
  limit?: number;
125
100
  after?: string;
@@ -127,7 +102,7 @@ interface Params {
127
102
  }
128
103
  interface Response$1<T> {
129
104
  data: T;
130
- _raw?: any;
105
+ _raw?: unknown;
131
106
  metadata: {
132
107
  next: string | null;
133
108
  };
@@ -139,7 +114,7 @@ declare abstract class Base {
139
114
  private version;
140
115
  protected abstract namespace: string;
141
116
  protected get headers(): Record<string, string>;
142
- protected buildUrl(path?: string | null, searchParams?: Record<string, any>): URL;
117
+ protected buildUrl(path?: string | null, searchParams?: Record<string, string | number | undefined>): URL;
143
118
  constructor(apiKey: string, connectionId: string);
144
119
  }
145
120
 
@@ -271,10 +246,6 @@ declare class BundleUp {
271
246
  * Access the Webhooks resource.
272
247
  */
273
248
  get webhooks(): Webhooks;
274
- /**
275
- * Access the Sessions resource.
276
- */
277
- get sessions(): Sessions;
278
249
  /**
279
250
  * Create a Proxy instance for a specific connection.
280
251
  * @param connectionId - The ID of the connection.
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ declare abstract class Base$1<T> {
4
4
  private baseUrl;
5
5
  private version;
6
6
  constructor(apiKey: string);
7
- protected buildUrl(path?: string | null, searchParams?: Record<string, any>): URL;
7
+ protected buildUrl(path?: string | null, searchParams?: Record<string, string>): URL;
8
8
  protected get headers(): Record<string, string>;
9
9
  /**
10
10
  * List resources with optional query parameters.
@@ -12,14 +12,14 @@ declare abstract class Base$1<T> {
12
12
  * @returns A promise that resolves to an array of resources.
13
13
  * @throws If params is not an object or if the fetch request fails.
14
14
  */
15
- list<K extends Record<string, any>>(searchParams?: K): Promise<T[]>;
15
+ list<K extends Record<string, string>>(searchParams?: K): Promise<T[]>;
16
16
  /**
17
17
  * Create a new resource.
18
18
  * @param body - The request body containing resource details.
19
19
  * @returns A promise that resolves to the created resource.
20
20
  * @throws If body is not an object or if the fetch request fails.
21
21
  */
22
- create<K extends Record<string, any>>(body: K): Promise<T>;
22
+ create<K extends Record<string, unknown>>(body: K): Promise<T>;
23
23
  /**
24
24
  * Retrieve a specific resource by ID.
25
25
  * @param id - The ID of the resource to retrieve.
@@ -34,7 +34,7 @@ declare abstract class Base$1<T> {
34
34
  * @returns A promise that resolves to the updated resource.
35
35
  * @throws If id is not provided, if body is not an object, or if the fetch request fails.
36
36
  */
37
- update<K extends Record<string, any>>(id: string, body: K): Promise<T>;
37
+ update<K extends Record<string, unknown>>(id: string, body: K): Promise<T>;
38
38
  /**
39
39
  * Delete a specific resource by ID.
40
40
  * @param id - The ID of the resource to delete.
@@ -88,38 +88,13 @@ declare class Proxy {
88
88
  private get headers();
89
89
  constructor(apiKey: string, connectionId: string);
90
90
  private buildUrl;
91
- get(path: string, searchParams?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
92
- post(path: string, body?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
93
- put(path: string, body?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
94
- patch(path: string, body?: Record<string, any>, headers?: Record<string, string>): Promise<Response>;
91
+ get(path: string, headers?: Record<string, string>): Promise<Response>;
92
+ post(path: string, body: BodyInit, headers?: Record<string, string>): Promise<Response>;
93
+ put(path: string, body: BodyInit, headers?: Record<string, string>): Promise<Response>;
94
+ patch(path: string, body: BodyInit, headers?: Record<string, string>): Promise<Response>;
95
95
  delete(path: string, headers?: Record<string, string>): Promise<Response>;
96
96
  }
97
97
 
98
- interface SessionCreateRequest {
99
- integrationId: string;
100
- externalId?: string;
101
- metadata?: Record<string, any>;
102
- redirectUri?: string;
103
- }
104
- interface SessionCreateResponse {
105
- token: string;
106
- auth_url: string;
107
- expires_in: number;
108
- external_id?: string;
109
- }
110
- declare class Sessions {
111
- private apiKey;
112
- constructor(apiKey: string);
113
- private get headers();
114
- /**
115
- * Create a new session.
116
- * @param params - The session creation parameters.
117
- * @returns A promise that resolves to the created session details.
118
- * @throws If the fetch request fails.
119
- */
120
- create(params: SessionCreateRequest): Promise<SessionCreateResponse>;
121
- }
122
-
123
98
  interface Params {
124
99
  limit?: number;
125
100
  after?: string;
@@ -127,7 +102,7 @@ interface Params {
127
102
  }
128
103
  interface Response$1<T> {
129
104
  data: T;
130
- _raw?: any;
105
+ _raw?: unknown;
131
106
  metadata: {
132
107
  next: string | null;
133
108
  };
@@ -139,7 +114,7 @@ declare abstract class Base {
139
114
  private version;
140
115
  protected abstract namespace: string;
141
116
  protected get headers(): Record<string, string>;
142
- protected buildUrl(path?: string | null, searchParams?: Record<string, any>): URL;
117
+ protected buildUrl(path?: string | null, searchParams?: Record<string, string | number | undefined>): URL;
143
118
  constructor(apiKey: string, connectionId: string);
144
119
  }
145
120
 
@@ -271,10 +246,6 @@ declare class BundleUp {
271
246
  * Access the Webhooks resource.
272
247
  */
273
248
  get webhooks(): Webhooks;
274
- /**
275
- * Access the Sessions resource.
276
- */
277
- get sessions(): Sessions;
278
249
  /**
279
250
  * Create a Proxy instance for a specific connection.
280
251
  * @param connectionId - The ID of the connection.
package/dist/index.js CHANGED
@@ -41,6 +41,15 @@ var Base = class {
41
41
  throw new Error("URL search params must be an object.");
42
42
  }
43
43
  const parts = [this.version, this.namespace, path].filter(Boolean).join("/");
44
+ searchParams = Object.entries(searchParams).reduce(
45
+ (acc, [key, value]) => {
46
+ if (value !== void 0 && value !== null) {
47
+ acc[key] = value;
48
+ }
49
+ return acc;
50
+ },
51
+ {}
52
+ );
44
53
  const url = new URL(parts, this.baseUrl);
45
54
  url.search = new URLSearchParams(searchParams).toString();
46
55
  return url;
@@ -67,9 +76,7 @@ var Base = class {
67
76
  headers: this.headers
68
77
  });
69
78
  if (!response.ok) {
70
- throw new Error(
71
- `Failed to fetch ${url.toString()}: ${response.statusText}`
72
- );
79
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
73
80
  }
74
81
  const data = await response.json();
75
82
  return data;
@@ -91,9 +98,7 @@ var Base = class {
91
98
  body: JSON.stringify(body)
92
99
  });
93
100
  if (!response.ok) {
94
- throw new Error(
95
- `Failed to create ${url.toString()}: ${response.statusText}`
96
- );
101
+ throw new Error(`Failed to create ${url.toString()}: ${response.statusText}`);
97
102
  }
98
103
  const data = await response.json();
99
104
  return data;
@@ -114,9 +119,7 @@ var Base = class {
114
119
  headers: this.headers
115
120
  });
116
121
  if (!response.ok) {
117
- throw new Error(
118
- `Failed to retrieve ${url.toString()}: ${response.statusText}`
119
- );
122
+ throw new Error(`Failed to retrieve ${url.toString()}: ${response.statusText}`);
120
123
  }
121
124
  const data = await response.json();
122
125
  return data;
@@ -142,9 +145,7 @@ var Base = class {
142
145
  body: JSON.stringify(body)
143
146
  });
144
147
  if (!response.ok) {
145
- throw new Error(
146
- `Failed to update ${url.toString()}: ${response.statusText}`
147
- );
148
+ throw new Error(`Failed to update ${url.toString()}: ${response.statusText}`);
148
149
  }
149
150
  const data = await response.json();
150
151
  return data;
@@ -165,9 +166,7 @@ var Base = class {
165
166
  headers: this.headers
166
167
  });
167
168
  if (!response.ok) {
168
- throw new Error(
169
- `Failed to delete ${url.toString()}: ${response.statusText}`
170
- );
169
+ throw new Error(`Failed to delete ${url.toString()}: ${response.statusText}`);
171
170
  }
172
171
  }
173
172
  };
@@ -210,85 +209,69 @@ var Proxy2 = class {
210
209
  "BU-Connection-Id": this.connectionId
211
210
  };
212
211
  }
213
- buildUrl(path, searchParams = {}) {
212
+ buildUrl(path) {
214
213
  if (!path) {
215
214
  throw new Error("Path is required to build URL.");
216
215
  }
217
- if (!isObject(searchParams)) {
218
- throw new Error("URL search params must be an object.");
219
- }
220
216
  if (!path.startsWith("/")) {
221
217
  path = `/${path}`;
222
218
  }
223
219
  const url = new URL(path, this.baseUrl);
224
- url.search = new URLSearchParams(searchParams).toString();
225
220
  return url;
226
221
  }
227
- get(path, searchParams = {}, headers = {}) {
222
+ get(path, headers = {}) {
228
223
  if (!path) {
229
224
  throw new Error("Path is required for GET request.");
230
225
  }
231
226
  if (!isObject(headers)) {
232
227
  throw new Error("Headers must be an object.");
233
228
  }
234
- if (!isObject(searchParams)) {
235
- throw new Error("URL search params must be an object.");
236
- }
237
- const url = this.buildUrl(path, searchParams);
229
+ const url = this.buildUrl(path);
238
230
  return fetch(url, {
239
231
  method: "GET",
240
232
  headers: { ...this.headers, ...headers }
241
233
  });
242
234
  }
243
- post(path, body = {}, headers = {}) {
235
+ post(path, body, headers = {}) {
244
236
  if (!path) {
245
237
  throw new Error("Path is required for POST request.");
246
238
  }
247
239
  if (!isObject(headers)) {
248
240
  throw new Error("Headers must be an object.");
249
241
  }
250
- if (!isObject(body)) {
251
- throw new Error("Request body must be an object.");
252
- }
253
242
  const url = this.buildUrl(path);
254
243
  return fetch(url, {
244
+ body,
255
245
  method: "POST",
256
- headers: { ...this.headers, ...headers },
257
- body: JSON.stringify(body)
246
+ headers: { ...this.headers, ...headers }
258
247
  });
259
248
  }
260
- put(path, body = {}, headers = {}) {
249
+ put(path, body, headers = {}) {
261
250
  if (!path) {
262
251
  throw new Error("Path is required for PUT request.");
263
252
  }
264
253
  if (!isObject(headers)) {
265
254
  throw new Error("Headers must be an object.");
266
255
  }
267
- if (!isObject(body)) {
268
- throw new Error("Request body must be an object.");
269
- }
270
256
  const url = this.buildUrl(path);
271
257
  return fetch(url, {
258
+ body,
272
259
  method: "PUT",
273
- headers: { ...this.headers, ...headers },
274
- body: JSON.stringify(body)
260
+ headers: { ...this.headers, ...headers }
275
261
  });
276
262
  }
277
- patch(path, body = {}, headers = {}) {
263
+ patch(path, body, headers = {}) {
278
264
  if (!path) {
279
265
  throw new Error("Path is required for PATCH request.");
280
266
  }
281
267
  if (!isObject(headers)) {
282
268
  throw new Error("Headers must be an object.");
283
269
  }
284
- if (!isObject(body)) {
285
- throw new Error("Request body must be an object.");
286
- }
287
270
  const url = this.buildUrl(path);
288
271
  return fetch(url, {
272
+ body,
289
273
  method: "PATCH",
290
- headers: { ...this.headers, ...headers },
291
- body: JSON.stringify(body)
274
+ headers: { ...this.headers, ...headers }
292
275
  });
293
276
  }
294
277
  delete(path, headers = {}) {
@@ -306,37 +289,6 @@ var Proxy2 = class {
306
289
  }
307
290
  };
308
291
 
309
- // src/session.ts
310
- var Sessions = class {
311
- constructor(apiKey) {
312
- this.apiKey = apiKey;
313
- }
314
- get headers() {
315
- return {
316
- "Content-Type": "application/json",
317
- Authorization: `Bearer ${this.apiKey}`
318
- };
319
- }
320
- /**
321
- * Create a new session.
322
- * @param params - The session creation parameters.
323
- * @returns A promise that resolves to the created session details.
324
- * @throws If the fetch request fails.
325
- */
326
- async create(params) {
327
- const response = await fetch("https://api.bundleup.io/v1/sessions", {
328
- method: "POST",
329
- headers: this.headers,
330
- body: JSON.stringify(params)
331
- });
332
- if (!response.ok) {
333
- throw new Error("Failed to create session");
334
- }
335
- const data = await response.json();
336
- return data;
337
- }
338
- };
339
-
340
292
  // src/unify/base.ts
341
293
  var Base2 = class {
342
294
  constructor(apiKey, connectionId) {
@@ -357,8 +309,17 @@ var Base2 = class {
357
309
  throw new Error("URL search params must be an object.");
358
310
  }
359
311
  const parts = [this.version, this.namespace, path].filter(Boolean).join("/");
312
+ const parsedSearchParams = Object.entries(searchParams).reduce(
313
+ (acc, [key, value]) => {
314
+ if (value !== void 0 && value !== null) {
315
+ acc[key] = value.toString();
316
+ }
317
+ return acc;
318
+ },
319
+ {}
320
+ );
360
321
  const url = new URL(parts, this.baseUrl);
361
- url.search = new URLSearchParams(searchParams).toString();
322
+ url.search = new URLSearchParams(parsedSearchParams).toString();
362
323
  return url;
363
324
  }
364
325
  };
@@ -385,9 +346,7 @@ var Chat = class extends Base2 {
385
346
  }
386
347
  });
387
348
  if (!response.ok) {
388
- throw new Error(
389
- `Failed to fetch ${url.toString()}: ${response.statusText}`
390
- );
349
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
391
350
  }
392
351
  const data = await response.json();
393
352
  return data;
@@ -416,9 +375,7 @@ var Git = class extends Base2 {
416
375
  }
417
376
  });
418
377
  if (!response.ok) {
419
- throw new Error(
420
- `Failed to fetch ${url.toString()}: ${response.statusText}`
421
- );
378
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
422
379
  }
423
380
  const data = await response.json();
424
381
  return data;
@@ -447,9 +404,7 @@ var Git = class extends Base2 {
447
404
  }
448
405
  });
449
406
  if (!response.ok) {
450
- throw new Error(
451
- `Failed to fetch ${url.toString()}: ${response.statusText}`
452
- );
407
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
453
408
  }
454
409
  const data = await response.json();
455
410
  return data;
@@ -478,9 +433,7 @@ var Git = class extends Base2 {
478
433
  }
479
434
  });
480
435
  if (!response.ok) {
481
- throw new Error(
482
- `Failed to fetch ${url.toString()}: ${response.statusText}`
483
- );
436
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
484
437
  }
485
438
  const data = await response.json();
486
439
  return data;
@@ -498,13 +451,10 @@ var Git = class extends Base2 {
498
451
  if (!repoName) {
499
452
  throw new Error("repoName is required to fetch releases.");
500
453
  }
501
- const url = this.buildUrl(
502
- `repos/${encodeURIComponent(repoName)}/releases`,
503
- {
504
- limit,
505
- after
506
- }
507
- );
454
+ const url = this.buildUrl(`repos/${encodeURIComponent(repoName)}/releases`, {
455
+ limit,
456
+ after
457
+ });
508
458
  const response = await fetch(url, {
509
459
  headers: {
510
460
  ...this.headers,
@@ -512,9 +462,7 @@ var Git = class extends Base2 {
512
462
  }
513
463
  });
514
464
  if (!response.ok) {
515
- throw new Error(
516
- `Failed to fetch ${url.toString()}: ${response.statusText}`
517
- );
465
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
518
466
  }
519
467
  const data = await response.json();
520
468
  return data;
@@ -543,9 +491,7 @@ var PM = class extends Base2 {
543
491
  }
544
492
  });
545
493
  if (!response.ok) {
546
- throw new Error(
547
- `Failed to fetch ${url.toString()}: ${response.statusText}`
548
- );
494
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
549
495
  }
550
496
  const data = await response.json();
551
497
  return data;
@@ -578,12 +524,6 @@ var BundleUp = class {
578
524
  get webhooks() {
579
525
  return new Webhooks(this.apiKey);
580
526
  }
581
- /**
582
- * Access the Sessions resource.
583
- */
584
- get sessions() {
585
- return new Sessions(this.apiKey);
586
- }
587
527
  /**
588
528
  * Create a Proxy instance for a specific connection.
589
529
  * @param connectionId - The ID of the connection.
package/dist/index.mjs CHANGED
@@ -15,6 +15,15 @@ var Base = class {
15
15
  throw new Error("URL search params must be an object.");
16
16
  }
17
17
  const parts = [this.version, this.namespace, path].filter(Boolean).join("/");
18
+ searchParams = Object.entries(searchParams).reduce(
19
+ (acc, [key, value]) => {
20
+ if (value !== void 0 && value !== null) {
21
+ acc[key] = value;
22
+ }
23
+ return acc;
24
+ },
25
+ {}
26
+ );
18
27
  const url = new URL(parts, this.baseUrl);
19
28
  url.search = new URLSearchParams(searchParams).toString();
20
29
  return url;
@@ -41,9 +50,7 @@ var Base = class {
41
50
  headers: this.headers
42
51
  });
43
52
  if (!response.ok) {
44
- throw new Error(
45
- `Failed to fetch ${url.toString()}: ${response.statusText}`
46
- );
53
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
47
54
  }
48
55
  const data = await response.json();
49
56
  return data;
@@ -65,9 +72,7 @@ var Base = class {
65
72
  body: JSON.stringify(body)
66
73
  });
67
74
  if (!response.ok) {
68
- throw new Error(
69
- `Failed to create ${url.toString()}: ${response.statusText}`
70
- );
75
+ throw new Error(`Failed to create ${url.toString()}: ${response.statusText}`);
71
76
  }
72
77
  const data = await response.json();
73
78
  return data;
@@ -88,9 +93,7 @@ var Base = class {
88
93
  headers: this.headers
89
94
  });
90
95
  if (!response.ok) {
91
- throw new Error(
92
- `Failed to retrieve ${url.toString()}: ${response.statusText}`
93
- );
96
+ throw new Error(`Failed to retrieve ${url.toString()}: ${response.statusText}`);
94
97
  }
95
98
  const data = await response.json();
96
99
  return data;
@@ -116,9 +119,7 @@ var Base = class {
116
119
  body: JSON.stringify(body)
117
120
  });
118
121
  if (!response.ok) {
119
- throw new Error(
120
- `Failed to update ${url.toString()}: ${response.statusText}`
121
- );
122
+ throw new Error(`Failed to update ${url.toString()}: ${response.statusText}`);
122
123
  }
123
124
  const data = await response.json();
124
125
  return data;
@@ -139,9 +140,7 @@ var Base = class {
139
140
  headers: this.headers
140
141
  });
141
142
  if (!response.ok) {
142
- throw new Error(
143
- `Failed to delete ${url.toString()}: ${response.statusText}`
144
- );
143
+ throw new Error(`Failed to delete ${url.toString()}: ${response.statusText}`);
145
144
  }
146
145
  }
147
146
  };
@@ -184,85 +183,69 @@ var Proxy = class {
184
183
  "BU-Connection-Id": this.connectionId
185
184
  };
186
185
  }
187
- buildUrl(path, searchParams = {}) {
186
+ buildUrl(path) {
188
187
  if (!path) {
189
188
  throw new Error("Path is required to build URL.");
190
189
  }
191
- if (!isObject(searchParams)) {
192
- throw new Error("URL search params must be an object.");
193
- }
194
190
  if (!path.startsWith("/")) {
195
191
  path = `/${path}`;
196
192
  }
197
193
  const url = new URL(path, this.baseUrl);
198
- url.search = new URLSearchParams(searchParams).toString();
199
194
  return url;
200
195
  }
201
- get(path, searchParams = {}, headers = {}) {
196
+ get(path, headers = {}) {
202
197
  if (!path) {
203
198
  throw new Error("Path is required for GET request.");
204
199
  }
205
200
  if (!isObject(headers)) {
206
201
  throw new Error("Headers must be an object.");
207
202
  }
208
- if (!isObject(searchParams)) {
209
- throw new Error("URL search params must be an object.");
210
- }
211
- const url = this.buildUrl(path, searchParams);
203
+ const url = this.buildUrl(path);
212
204
  return fetch(url, {
213
205
  method: "GET",
214
206
  headers: { ...this.headers, ...headers }
215
207
  });
216
208
  }
217
- post(path, body = {}, headers = {}) {
209
+ post(path, body, headers = {}) {
218
210
  if (!path) {
219
211
  throw new Error("Path is required for POST request.");
220
212
  }
221
213
  if (!isObject(headers)) {
222
214
  throw new Error("Headers must be an object.");
223
215
  }
224
- if (!isObject(body)) {
225
- throw new Error("Request body must be an object.");
226
- }
227
216
  const url = this.buildUrl(path);
228
217
  return fetch(url, {
218
+ body,
229
219
  method: "POST",
230
- headers: { ...this.headers, ...headers },
231
- body: JSON.stringify(body)
220
+ headers: { ...this.headers, ...headers }
232
221
  });
233
222
  }
234
- put(path, body = {}, headers = {}) {
223
+ put(path, body, headers = {}) {
235
224
  if (!path) {
236
225
  throw new Error("Path is required for PUT request.");
237
226
  }
238
227
  if (!isObject(headers)) {
239
228
  throw new Error("Headers must be an object.");
240
229
  }
241
- if (!isObject(body)) {
242
- throw new Error("Request body must be an object.");
243
- }
244
230
  const url = this.buildUrl(path);
245
231
  return fetch(url, {
232
+ body,
246
233
  method: "PUT",
247
- headers: { ...this.headers, ...headers },
248
- body: JSON.stringify(body)
234
+ headers: { ...this.headers, ...headers }
249
235
  });
250
236
  }
251
- patch(path, body = {}, headers = {}) {
237
+ patch(path, body, headers = {}) {
252
238
  if (!path) {
253
239
  throw new Error("Path is required for PATCH request.");
254
240
  }
255
241
  if (!isObject(headers)) {
256
242
  throw new Error("Headers must be an object.");
257
243
  }
258
- if (!isObject(body)) {
259
- throw new Error("Request body must be an object.");
260
- }
261
244
  const url = this.buildUrl(path);
262
245
  return fetch(url, {
246
+ body,
263
247
  method: "PATCH",
264
- headers: { ...this.headers, ...headers },
265
- body: JSON.stringify(body)
248
+ headers: { ...this.headers, ...headers }
266
249
  });
267
250
  }
268
251
  delete(path, headers = {}) {
@@ -280,37 +263,6 @@ var Proxy = class {
280
263
  }
281
264
  };
282
265
 
283
- // src/session.ts
284
- var Sessions = class {
285
- constructor(apiKey) {
286
- this.apiKey = apiKey;
287
- }
288
- get headers() {
289
- return {
290
- "Content-Type": "application/json",
291
- Authorization: `Bearer ${this.apiKey}`
292
- };
293
- }
294
- /**
295
- * Create a new session.
296
- * @param params - The session creation parameters.
297
- * @returns A promise that resolves to the created session details.
298
- * @throws If the fetch request fails.
299
- */
300
- async create(params) {
301
- const response = await fetch("https://api.bundleup.io/v1/sessions", {
302
- method: "POST",
303
- headers: this.headers,
304
- body: JSON.stringify(params)
305
- });
306
- if (!response.ok) {
307
- throw new Error("Failed to create session");
308
- }
309
- const data = await response.json();
310
- return data;
311
- }
312
- };
313
-
314
266
  // src/unify/base.ts
315
267
  var Base2 = class {
316
268
  constructor(apiKey, connectionId) {
@@ -331,8 +283,17 @@ var Base2 = class {
331
283
  throw new Error("URL search params must be an object.");
332
284
  }
333
285
  const parts = [this.version, this.namespace, path].filter(Boolean).join("/");
286
+ const parsedSearchParams = Object.entries(searchParams).reduce(
287
+ (acc, [key, value]) => {
288
+ if (value !== void 0 && value !== null) {
289
+ acc[key] = value.toString();
290
+ }
291
+ return acc;
292
+ },
293
+ {}
294
+ );
334
295
  const url = new URL(parts, this.baseUrl);
335
- url.search = new URLSearchParams(searchParams).toString();
296
+ url.search = new URLSearchParams(parsedSearchParams).toString();
336
297
  return url;
337
298
  }
338
299
  };
@@ -359,9 +320,7 @@ var Chat = class extends Base2 {
359
320
  }
360
321
  });
361
322
  if (!response.ok) {
362
- throw new Error(
363
- `Failed to fetch ${url.toString()}: ${response.statusText}`
364
- );
323
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
365
324
  }
366
325
  const data = await response.json();
367
326
  return data;
@@ -390,9 +349,7 @@ var Git = class extends Base2 {
390
349
  }
391
350
  });
392
351
  if (!response.ok) {
393
- throw new Error(
394
- `Failed to fetch ${url.toString()}: ${response.statusText}`
395
- );
352
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
396
353
  }
397
354
  const data = await response.json();
398
355
  return data;
@@ -421,9 +378,7 @@ var Git = class extends Base2 {
421
378
  }
422
379
  });
423
380
  if (!response.ok) {
424
- throw new Error(
425
- `Failed to fetch ${url.toString()}: ${response.statusText}`
426
- );
381
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
427
382
  }
428
383
  const data = await response.json();
429
384
  return data;
@@ -452,9 +407,7 @@ var Git = class extends Base2 {
452
407
  }
453
408
  });
454
409
  if (!response.ok) {
455
- throw new Error(
456
- `Failed to fetch ${url.toString()}: ${response.statusText}`
457
- );
410
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
458
411
  }
459
412
  const data = await response.json();
460
413
  return data;
@@ -472,13 +425,10 @@ var Git = class extends Base2 {
472
425
  if (!repoName) {
473
426
  throw new Error("repoName is required to fetch releases.");
474
427
  }
475
- const url = this.buildUrl(
476
- `repos/${encodeURIComponent(repoName)}/releases`,
477
- {
478
- limit,
479
- after
480
- }
481
- );
428
+ const url = this.buildUrl(`repos/${encodeURIComponent(repoName)}/releases`, {
429
+ limit,
430
+ after
431
+ });
482
432
  const response = await fetch(url, {
483
433
  headers: {
484
434
  ...this.headers,
@@ -486,9 +436,7 @@ var Git = class extends Base2 {
486
436
  }
487
437
  });
488
438
  if (!response.ok) {
489
- throw new Error(
490
- `Failed to fetch ${url.toString()}: ${response.statusText}`
491
- );
439
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
492
440
  }
493
441
  const data = await response.json();
494
442
  return data;
@@ -517,9 +465,7 @@ var PM = class extends Base2 {
517
465
  }
518
466
  });
519
467
  if (!response.ok) {
520
- throw new Error(
521
- `Failed to fetch ${url.toString()}: ${response.statusText}`
522
- );
468
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.statusText}`);
523
469
  }
524
470
  const data = await response.json();
525
471
  return data;
@@ -552,12 +498,6 @@ var BundleUp = class {
552
498
  get webhooks() {
553
499
  return new Webhooks(this.apiKey);
554
500
  }
555
- /**
556
- * Access the Sessions resource.
557
- */
558
- get sessions() {
559
- return new Sessions(this.apiKey);
560
- }
561
501
  /**
562
502
  * Create a Proxy instance for a specific connection.
563
503
  * @param connectionId - The ID of the connection.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bundleup/sdk",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "SDK package for BundleUp",
5
5
  "exports": {
6
6
  ".": {
@@ -12,7 +12,7 @@
12
12
  "scripts": {
13
13
  "build": "tsup src/index.ts --format cjs,esm --dts",
14
14
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
15
- "lint": "eslint src/",
15
+ "lint": "eslint src",
16
16
  "test": "jest",
17
17
  "clean": "rm -rf dist"
18
18
  },
@@ -21,8 +21,7 @@
21
21
  "jest": "^29.0.0",
22
22
  "ts-jest": "^29.1.0",
23
23
  "tsup": "^7.0.0",
24
- "typescript": "^5.0.0",
25
- "eslint": "^8.0.0"
24
+ "typescript": "^5.0.0"
26
25
  },
27
26
  "files": [
28
27
  "dist"