@hasna/connectors 1.3.22 → 1.3.23
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/bin/index.js +109 -59
- package/bin/mcp.js +236 -182
- package/bin/serve.js +77 -33
- package/connectors/connect-dropbox/src/api/bulk.ts +285 -0
- package/connectors/connect-dropbox/src/api/index.ts +4 -0
- package/connectors/connect-dropbox/src/cli/index.ts +151 -0
- package/connectors/connect-github/src/api/bulk.ts +328 -0
- package/connectors/connect-github/src/api/index.ts +4 -0
- package/connectors/connect-github/src/cli/index.ts +145 -0
- package/connectors/connect-gmail/src/api/history.ts +82 -0
- package/connectors/connect-gmail/src/api/index.ts +12 -0
- package/connectors/connect-gmail/src/api/settings.ts +280 -0
- package/connectors/connect-gmail/src/api/watch.ts +40 -0
- package/connectors/connect-gmail/src/cli/index.ts +237 -0
- package/connectors/connect-googleads/src/api/bulk.ts +354 -0
- package/connectors/connect-googleads/src/api/index.ts +4 -0
- package/connectors/connect-googleads/src/cli/index.ts +192 -0
- package/connectors/connect-googlecalendar/src/api/acl.ts +66 -0
- package/connectors/connect-googlecalendar/src/api/bulk.ts +452 -0
- package/connectors/connect-googlecalendar/src/api/freebusy.ts +35 -0
- package/connectors/connect-googlecalendar/src/api/index.ts +9 -0
- package/connectors/connect-googlecalendar/src/cli/index.ts +522 -0
- package/connectors/connect-googlecalendar/src/types/index.ts +90 -0
- package/connectors/connect-googlecontacts/src/api/bulk.ts +365 -0
- package/connectors/connect-googlecontacts/src/api/groups.ts +164 -0
- package/connectors/connect-googlecontacts/src/api/index.ts +8 -0
- package/connectors/connect-googlecontacts/src/cli/index.ts +340 -0
- package/connectors/connect-googledocs/src/api/bulk.ts +301 -0
- package/connectors/connect-googledocs/src/api/index.ts +4 -0
- package/connectors/connect-googledocs/src/cli/index.ts +187 -0
- package/connectors/connect-googledrive/src/api/bulk.ts +505 -0
- package/connectors/connect-googledrive/src/api/changes.ts +139 -0
- package/connectors/connect-googledrive/src/api/client.ts +34 -0
- package/connectors/connect-googledrive/src/api/index.ts +12 -0
- package/connectors/connect-googledrive/src/api/revisions.ts +132 -0
- package/connectors/connect-googledrive/src/cli/index.ts +624 -0
- package/connectors/connect-googledrive/src/index.ts +2 -0
- package/connectors/connect-googlephotos/src/api/bulk.ts +455 -0
- package/connectors/connect-googlephotos/src/api/index.ts +8 -0
- package/connectors/connect-googlephotos/src/cli/index.ts +185 -0
- package/connectors/connect-googletasks/src/api/bulk.ts +359 -0
- package/connectors/connect-googletasks/src/api/index.ts +1 -0
- package/connectors/connect-googletasks/src/cli/index.ts +178 -0
- package/connectors/connect-linear/src/api/bulk.ts +219 -0
- package/connectors/connect-linear/src/api/index.ts +4 -0
- package/connectors/connect-linear/src/cli/index.ts +116 -0
- package/connectors/connect-shopify/src/api/bulk.ts +288 -0
- package/connectors/connect-shopify/src/api/index.ts +4 -0
- package/connectors/connect-shopify/src/cli/index.ts +108 -0
- package/connectors/connect-slack/src/api/bulk.ts +237 -0
- package/connectors/connect-slack/src/api/index.ts +4 -0
- package/connectors/connect-slack/src/cli/index.ts +157 -0
- package/connectors/connect-stripe/src/api/bulk.ts +488 -0
- package/connectors/connect-stripe/src/api/index.ts +4 -0
- package/connectors/connect-stripe/src/cli/index.ts +206 -0
- package/dist/index.js +75 -33
- package/dist/lib/runner.d.ts +15 -5
- package/package.json +2 -2
- package/connectors/connect-cloudflare/bun.lock +0 -32
- package/connectors/connect-gmail/bin/index.js +0 -7027
- package/connectors/connect-gmail/dist/cli/index.js +0 -7035
- package/connectors/connect-gmail/dist/index.js +0 -2174
- package/dist/server/server.test.d.ts +0 -1
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import type { ConnectorClient } from './client';
|
|
2
|
+
import type { DeletedObject, Metadata } from '../types';
|
|
3
|
+
|
|
4
|
+
// ============================================
|
|
5
|
+
// Bulk Operation Types
|
|
6
|
+
// ============================================
|
|
7
|
+
|
|
8
|
+
export interface BulkOperationOptions {
|
|
9
|
+
/** Maximum concurrent API calls (default: 10) */
|
|
10
|
+
concurrency?: number;
|
|
11
|
+
/** Dry run - don't actually modify */
|
|
12
|
+
dryRun?: boolean;
|
|
13
|
+
/** Progress callback */
|
|
14
|
+
onProgress?: (current: number, total: number, item: unknown) => void;
|
|
15
|
+
/** Error callback */
|
|
16
|
+
onError?: (error: Error, item: unknown) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// --- Product Bulk Operations ---
|
|
20
|
+
|
|
21
|
+
export interface BulkProductOptions extends BulkOperationOptions {
|
|
22
|
+
productIds: string[];
|
|
23
|
+
/** Action to perform */
|
|
24
|
+
action: 'delete' | 'activate' | 'deactivate';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface BulkProductResult {
|
|
28
|
+
total: number;
|
|
29
|
+
success: number;
|
|
30
|
+
failed: number;
|
|
31
|
+
errors: Array<{ productId: string; error: string }>;
|
|
32
|
+
results: Array<{ productId: string; response: unknown }>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// --- Price Bulk Operations ---
|
|
36
|
+
|
|
37
|
+
export interface BulkPriceOptions extends BulkOperationOptions {
|
|
38
|
+
priceIds: string[];
|
|
39
|
+
/** Action to perform */
|
|
40
|
+
action: 'activate' | 'deactivate';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface BulkPriceResult {
|
|
44
|
+
total: number;
|
|
45
|
+
success: number;
|
|
46
|
+
failed: number;
|
|
47
|
+
errors: Array<{ priceId: string; error: string }>;
|
|
48
|
+
results: Array<{ priceId: string; response: unknown }>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// --- Customer Bulk Operations ---
|
|
52
|
+
|
|
53
|
+
export interface BulkCustomerOptions extends BulkOperationOptions {
|
|
54
|
+
customerIds: string[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface BulkCustomerResult {
|
|
58
|
+
total: number;
|
|
59
|
+
success: number;
|
|
60
|
+
failed: number;
|
|
61
|
+
errors: Array<{ customerId: string; error: string }>;
|
|
62
|
+
results: Array<{ customerId: string; response: DeletedObject }>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// --- Subscription Bulk Operations ---
|
|
66
|
+
|
|
67
|
+
export interface BulkSubscriptionOptions extends BulkOperationOptions {
|
|
68
|
+
subscriptionIds: string[];
|
|
69
|
+
/** Action to perform */
|
|
70
|
+
action: 'cancel' | 'resume';
|
|
71
|
+
/** Cancel immediately instead of at period end */
|
|
72
|
+
cancelImmediately?: boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface BulkSubscriptionResult {
|
|
76
|
+
total: number;
|
|
77
|
+
success: number;
|
|
78
|
+
failed: number;
|
|
79
|
+
errors: Array<{ subscriptionId: string; error: string }>;
|
|
80
|
+
results: Array<{ subscriptionId: string; response: unknown }>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// --- Coupon Bulk Operations ---
|
|
84
|
+
|
|
85
|
+
export interface BulkCouponOptions extends BulkOperationOptions {
|
|
86
|
+
couponIds: string[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface BulkCouponResult {
|
|
90
|
+
total: number;
|
|
91
|
+
success: number;
|
|
92
|
+
failed: number;
|
|
93
|
+
errors: Array<{ couponId: string; error: string }>;
|
|
94
|
+
results: Array<{ couponId: string; response: DeletedObject }>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// --- Invoice Bulk Operations ---
|
|
98
|
+
|
|
99
|
+
export interface BulkInvoiceOptions extends BulkOperationOptions {
|
|
100
|
+
invoiceIds: string[];
|
|
101
|
+
/** Action to perform (only draft invoices can be deleted) */
|
|
102
|
+
action: 'delete' | 'void' | 'finalize';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface BulkInvoiceResult {
|
|
106
|
+
total: number;
|
|
107
|
+
success: number;
|
|
108
|
+
failed: number;
|
|
109
|
+
errors: Array<{ invoiceId: string; error: string }>;
|
|
110
|
+
results: Array<{ invoiceId: string; response: unknown }>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// --- Webhook Bulk Operations ---
|
|
114
|
+
|
|
115
|
+
export interface BulkWebhookOptions extends BulkOperationOptions {
|
|
116
|
+
webhookIds: string[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface BulkWebhookResult {
|
|
120
|
+
total: number;
|
|
121
|
+
success: number;
|
|
122
|
+
failed: number;
|
|
123
|
+
errors: Array<{ webhookId: string; error: string }>;
|
|
124
|
+
results: Array<{ webhookId: string; response: DeletedObject }>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============================================
|
|
128
|
+
// Bulk Operations API
|
|
129
|
+
// ============================================
|
|
130
|
+
|
|
131
|
+
export class BulkApi {
|
|
132
|
+
private readonly client: ConnectorClient;
|
|
133
|
+
|
|
134
|
+
constructor(client: ConnectorClient) {
|
|
135
|
+
this.client = client;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ============================================
|
|
139
|
+
// Bulk Product Operations
|
|
140
|
+
// ============================================
|
|
141
|
+
|
|
142
|
+
async products(options: BulkProductOptions): Promise<BulkProductResult> {
|
|
143
|
+
const { productIds, action, concurrency = 10, dryRun = false, onProgress, onError } = options;
|
|
144
|
+
|
|
145
|
+
const result: BulkProductResult = {
|
|
146
|
+
total: productIds.length,
|
|
147
|
+
success: 0,
|
|
148
|
+
failed: 0,
|
|
149
|
+
errors: [],
|
|
150
|
+
results: [],
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
if (productIds.length === 0) return result;
|
|
154
|
+
|
|
155
|
+
const chunks = this.chunkArray(productIds, concurrency);
|
|
156
|
+
|
|
157
|
+
for (const chunk of chunks) {
|
|
158
|
+
await Promise.all(
|
|
159
|
+
chunk.map(async (productId) => {
|
|
160
|
+
try {
|
|
161
|
+
if (dryRun) {
|
|
162
|
+
result.success++;
|
|
163
|
+
} else {
|
|
164
|
+
let response: unknown;
|
|
165
|
+
if (action === 'delete') {
|
|
166
|
+
response = await this.client.products.del(productId);
|
|
167
|
+
} else {
|
|
168
|
+
response = await this.client.products.update(productId, {
|
|
169
|
+
active: action === 'activate',
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
result.success++;
|
|
173
|
+
result.results.push({ productId, response });
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (onProgress) onProgress(result.success + result.failed, result.total, productId);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
result.failed++;
|
|
179
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
180
|
+
result.errors.push({ productId, error: errorMessage });
|
|
181
|
+
if (onError) onError(err instanceof Error ? err : new Error(errorMessage), productId);
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ============================================
|
|
191
|
+
// Bulk Price Operations
|
|
192
|
+
// ============================================
|
|
193
|
+
|
|
194
|
+
async prices(options: BulkPriceOptions): Promise<BulkPriceResult> {
|
|
195
|
+
const { priceIds, action, concurrency = 10, dryRun = false, onProgress, onError } = options;
|
|
196
|
+
|
|
197
|
+
const result: BulkPriceResult = {
|
|
198
|
+
total: priceIds.length,
|
|
199
|
+
success: 0,
|
|
200
|
+
failed: 0,
|
|
201
|
+
errors: [],
|
|
202
|
+
results: [],
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
if (priceIds.length === 0) return result;
|
|
206
|
+
|
|
207
|
+
const chunks = this.chunkArray(priceIds, concurrency);
|
|
208
|
+
|
|
209
|
+
for (const chunk of chunks) {
|
|
210
|
+
await Promise.all(
|
|
211
|
+
chunk.map(async (priceId) => {
|
|
212
|
+
try {
|
|
213
|
+
if (dryRun) {
|
|
214
|
+
result.success++;
|
|
215
|
+
} else {
|
|
216
|
+
const response = await this.client.prices.update(priceId, {
|
|
217
|
+
active: action === 'activate',
|
|
218
|
+
});
|
|
219
|
+
result.success++;
|
|
220
|
+
result.results.push({ priceId, response });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (onProgress) onProgress(result.success + result.failed, result.total, priceId);
|
|
224
|
+
} catch (err) {
|
|
225
|
+
result.failed++;
|
|
226
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
227
|
+
result.errors.push({ priceId, error: errorMessage });
|
|
228
|
+
if (onError) onError(err instanceof Error ? err : new Error(errorMessage), priceId);
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ============================================
|
|
238
|
+
// Bulk Customer Operations
|
|
239
|
+
// ============================================
|
|
240
|
+
|
|
241
|
+
async customers(options: BulkCustomerOptions): Promise<BulkCustomerResult> {
|
|
242
|
+
const { customerIds, concurrency = 10, dryRun = false, onProgress, onError } = options;
|
|
243
|
+
|
|
244
|
+
const result: BulkCustomerResult = {
|
|
245
|
+
total: customerIds.length,
|
|
246
|
+
success: 0,
|
|
247
|
+
failed: 0,
|
|
248
|
+
errors: [],
|
|
249
|
+
results: [],
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
if (customerIds.length === 0) return result;
|
|
253
|
+
|
|
254
|
+
const chunks = this.chunkArray(customerIds, concurrency);
|
|
255
|
+
|
|
256
|
+
for (const chunk of chunks) {
|
|
257
|
+
await Promise.all(
|
|
258
|
+
chunk.map(async (customerId) => {
|
|
259
|
+
try {
|
|
260
|
+
if (dryRun) {
|
|
261
|
+
result.success++;
|
|
262
|
+
} else {
|
|
263
|
+
const response = await this.client.customers.del(customerId);
|
|
264
|
+
result.success++;
|
|
265
|
+
result.results.push({ customerId, response });
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (onProgress) onProgress(result.success + result.failed, result.total, customerId);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
result.failed++;
|
|
271
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
272
|
+
result.errors.push({ customerId, error: errorMessage });
|
|
273
|
+
if (onError) onError(err instanceof Error ? err : new Error(errorMessage), customerId);
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ============================================
|
|
283
|
+
// Bulk Subscription Operations
|
|
284
|
+
// ============================================
|
|
285
|
+
|
|
286
|
+
async subscriptions(options: BulkSubscriptionOptions): Promise<BulkSubscriptionResult> {
|
|
287
|
+
const { subscriptionIds, action, cancelImmediately = false, concurrency = 10, dryRun = false, onProgress, onError } = options;
|
|
288
|
+
|
|
289
|
+
const result: BulkSubscriptionResult = {
|
|
290
|
+
total: subscriptionIds.length,
|
|
291
|
+
success: 0,
|
|
292
|
+
failed: 0,
|
|
293
|
+
errors: [],
|
|
294
|
+
results: [],
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
if (subscriptionIds.length === 0) return result;
|
|
298
|
+
|
|
299
|
+
const chunks = this.chunkArray(subscriptionIds, concurrency);
|
|
300
|
+
|
|
301
|
+
for (const chunk of chunks) {
|
|
302
|
+
await Promise.all(
|
|
303
|
+
chunk.map(async (subscriptionId) => {
|
|
304
|
+
try {
|
|
305
|
+
if (dryRun) {
|
|
306
|
+
result.success++;
|
|
307
|
+
} else {
|
|
308
|
+
let response: unknown;
|
|
309
|
+
if (action === 'cancel') {
|
|
310
|
+
response = await this.client.subscriptions.cancel(subscriptionId, {
|
|
311
|
+
prorate: cancelImmediately,
|
|
312
|
+
invoice_now: cancelImmediately,
|
|
313
|
+
});
|
|
314
|
+
} else {
|
|
315
|
+
response = await this.client.subscriptions.resume(subscriptionId);
|
|
316
|
+
}
|
|
317
|
+
result.success++;
|
|
318
|
+
result.results.push({ subscriptionId, response });
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (onProgress) onProgress(result.success + result.failed, result.total, subscriptionId);
|
|
322
|
+
} catch (err) {
|
|
323
|
+
result.failed++;
|
|
324
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
325
|
+
result.errors.push({ subscriptionId, error: errorMessage });
|
|
326
|
+
if (onError) onError(err instanceof Error ? err : new Error(errorMessage), subscriptionId);
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// ============================================
|
|
336
|
+
// Bulk Coupon Operations
|
|
337
|
+
// ============================================
|
|
338
|
+
|
|
339
|
+
async coupons(options: BulkCouponOptions): Promise<BulkCouponResult> {
|
|
340
|
+
const { couponIds, concurrency = 10, dryRun = false, onProgress, onError } = options;
|
|
341
|
+
|
|
342
|
+
const result: BulkCouponResult = {
|
|
343
|
+
total: couponIds.length,
|
|
344
|
+
success: 0,
|
|
345
|
+
failed: 0,
|
|
346
|
+
errors: [],
|
|
347
|
+
results: [],
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
if (couponIds.length === 0) return result;
|
|
351
|
+
|
|
352
|
+
const chunks = this.chunkArray(couponIds, concurrency);
|
|
353
|
+
|
|
354
|
+
for (const chunk of chunks) {
|
|
355
|
+
await Promise.all(
|
|
356
|
+
chunk.map(async (couponId) => {
|
|
357
|
+
try {
|
|
358
|
+
if (dryRun) {
|
|
359
|
+
result.success++;
|
|
360
|
+
} else {
|
|
361
|
+
const response = await this.client.coupons.del(couponId);
|
|
362
|
+
result.success++;
|
|
363
|
+
result.results.push({ couponId, response });
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (onProgress) onProgress(result.success + result.failed, result.total, couponId);
|
|
367
|
+
} catch (err) {
|
|
368
|
+
result.failed++;
|
|
369
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
370
|
+
result.errors.push({ couponId, error: errorMessage });
|
|
371
|
+
if (onError) onError(err instanceof Error ? err : new Error(errorMessage), couponId);
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return result;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// ============================================
|
|
381
|
+
// Bulk Invoice Operations
|
|
382
|
+
// ============================================
|
|
383
|
+
|
|
384
|
+
async invoices(options: BulkInvoiceOptions): Promise<BulkInvoiceResult> {
|
|
385
|
+
const { invoiceIds, action, concurrency = 10, dryRun = false, onProgress, onError } = options;
|
|
386
|
+
|
|
387
|
+
const result: BulkInvoiceResult = {
|
|
388
|
+
total: invoiceIds.length,
|
|
389
|
+
success: 0,
|
|
390
|
+
failed: 0,
|
|
391
|
+
errors: [],
|
|
392
|
+
results: [],
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
if (invoiceIds.length === 0) return result;
|
|
396
|
+
|
|
397
|
+
const chunks = this.chunkArray(invoiceIds, concurrency);
|
|
398
|
+
|
|
399
|
+
for (const chunk of chunks) {
|
|
400
|
+
await Promise.all(
|
|
401
|
+
chunk.map(async (invoiceId) => {
|
|
402
|
+
try {
|
|
403
|
+
if (dryRun) {
|
|
404
|
+
result.success++;
|
|
405
|
+
} else {
|
|
406
|
+
let response: unknown;
|
|
407
|
+
if (action === 'delete') {
|
|
408
|
+
response = await this.client.invoices.del(invoiceId);
|
|
409
|
+
} else if (action === 'void') {
|
|
410
|
+
response = await this.client.invoices.void(invoiceId);
|
|
411
|
+
} else {
|
|
412
|
+
response = await this.client.invoices.finalize(invoiceId);
|
|
413
|
+
}
|
|
414
|
+
result.success++;
|
|
415
|
+
result.results.push({ invoiceId, response });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (onProgress) onProgress(result.success + result.failed, result.total, invoiceId);
|
|
419
|
+
} catch (err) {
|
|
420
|
+
result.failed++;
|
|
421
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
422
|
+
result.errors.push({ invoiceId, error: errorMessage });
|
|
423
|
+
if (onError) onError(err instanceof Error ? err : new Error(errorMessage), invoiceId);
|
|
424
|
+
}
|
|
425
|
+
})
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// ============================================
|
|
433
|
+
// Bulk Webhook Operations
|
|
434
|
+
// ============================================
|
|
435
|
+
|
|
436
|
+
async webhooks(options: BulkWebhookOptions): Promise<BulkWebhookResult> {
|
|
437
|
+
const { webhookIds, concurrency = 10, dryRun = false, onProgress, onError } = options;
|
|
438
|
+
|
|
439
|
+
const result: BulkWebhookResult = {
|
|
440
|
+
total: webhookIds.length,
|
|
441
|
+
success: 0,
|
|
442
|
+
failed: 0,
|
|
443
|
+
errors: [],
|
|
444
|
+
results: [],
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
if (webhookIds.length === 0) return result;
|
|
448
|
+
|
|
449
|
+
const chunks = this.chunkArray(webhookIds, concurrency);
|
|
450
|
+
|
|
451
|
+
for (const chunk of chunks) {
|
|
452
|
+
await Promise.all(
|
|
453
|
+
chunk.map(async (webhookId) => {
|
|
454
|
+
try {
|
|
455
|
+
if (dryRun) {
|
|
456
|
+
result.success++;
|
|
457
|
+
} else {
|
|
458
|
+
const response = await this.client.webhooks.del(webhookId);
|
|
459
|
+
result.success++;
|
|
460
|
+
result.results.push({ webhookId, response });
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (onProgress) onProgress(result.success + result.failed, result.total, webhookId);
|
|
464
|
+
} catch (err) {
|
|
465
|
+
result.failed++;
|
|
466
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
467
|
+
result.errors.push({ webhookId, error: errorMessage });
|
|
468
|
+
if (onError) onError(err instanceof Error ? err : new Error(errorMessage), webhookId);
|
|
469
|
+
}
|
|
470
|
+
})
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return result;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// ============================================
|
|
478
|
+
// Helper Methods
|
|
479
|
+
// ============================================
|
|
480
|
+
|
|
481
|
+
private chunkArray<T>(array: T[], size: number): T[][] {
|
|
482
|
+
const chunks: T[][] = [];
|
|
483
|
+
for (let i = 0; i < array.length; i += size) {
|
|
484
|
+
chunks.push(array.slice(i, i + size));
|
|
485
|
+
}
|
|
486
|
+
return chunks;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
@@ -18,6 +18,7 @@ import { WebhooksApi } from './webhooks';
|
|
|
18
18
|
import { CheckoutSessionsApi } from './checkout-sessions';
|
|
19
19
|
import { PaymentLinksApi } from './payment-links';
|
|
20
20
|
import { BillingPortalApi } from './billing-portal';
|
|
21
|
+
import { BulkApi } from './bulk';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Stripe API Connector class
|
|
@@ -44,6 +45,7 @@ export class Connector {
|
|
|
44
45
|
public readonly checkoutSessions: CheckoutSessionsApi;
|
|
45
46
|
public readonly paymentLinks: PaymentLinksApi;
|
|
46
47
|
public readonly billingPortal: BillingPortalApi;
|
|
48
|
+
public readonly bulk: BulkApi;
|
|
47
49
|
|
|
48
50
|
constructor(config: ConnectorConfig) {
|
|
49
51
|
this.client = new ConnectorClient(config);
|
|
@@ -65,6 +67,7 @@ export class Connector {
|
|
|
65
67
|
this.checkoutSessions = new CheckoutSessionsApi(this.client);
|
|
66
68
|
this.paymentLinks = new PaymentLinksApi(this.client);
|
|
67
69
|
this.billingPortal = new BillingPortalApi(this.client);
|
|
70
|
+
this.bulk = new BulkApi(this.client);
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
/**
|
|
@@ -123,3 +126,4 @@ export { WebhooksApi } from './webhooks';
|
|
|
123
126
|
export { CheckoutSessionsApi } from './checkout-sessions';
|
|
124
127
|
export { PaymentLinksApi } from './payment-links';
|
|
125
128
|
export { BillingPortalApi } from './billing-portal';
|
|
129
|
+
export { BulkApi } from './bulk';
|