dragdropdo-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,621 @@
1
+ "use strict";
2
+ /**
3
+ * dragdropdo.com Business API Client
4
+ *
5
+ * A Node.js client library for interacting with the dragdropdo.com Business API.
6
+ * Provides methods for file uploads, operations, and status checking.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.Dragdropdo = void 0;
46
+ // Import statements - these will resolve when dependencies are installed
47
+ // @ts-ignore - Module resolution will work at runtime with installed dependencies
48
+ const axios_1 = __importDefault(require("axios"));
49
+ // @ts-ignore
50
+ const fs = __importStar(require("fs"));
51
+ // @ts-ignore
52
+ const path = __importStar(require("path"));
53
+ const errors_1 = require("./errors");
54
+ class Dragdropdo {
55
+ /**
56
+ * Create a new DragDropDo Client instance
57
+ *
58
+ * @param config - Client configuration
59
+ * @example
60
+ * ```typescript
61
+ * const client = new Dragdropdo({
62
+ * apiKey: 'your-api-key',
63
+ * baseURL: 'https://dragdropdo.com',
64
+ * timeout: 30000
65
+ * });
66
+ * ```
67
+ */
68
+ constructor(config) {
69
+ if (!config.apiKey) {
70
+ throw new errors_1.D3ValidationError("API key is required");
71
+ }
72
+ this.apiKey = config.apiKey;
73
+ this.baseURL = config.baseURL || "https://dragdropdo.com";
74
+ this.timeout = config.timeout || 30000;
75
+ // Remove trailing slash from baseURL
76
+ this.baseURL = this.baseURL.replace(/\/$/, "");
77
+ // Create axios instance with default config
78
+ this.axiosInstance = axios_1.default.create({
79
+ baseURL: this.baseURL,
80
+ timeout: this.timeout,
81
+ headers: {
82
+ "Content-Type": "application/json",
83
+ Authorization: `Bearer ${this.apiKey}`,
84
+ ...config.headers,
85
+ },
86
+ });
87
+ // Add response interceptor for error handling
88
+ this.axiosInstance.interceptors.response.use((response) => response, (error) => {
89
+ if (error.response) {
90
+ const { status, data } = error.response;
91
+ const message = data?.message ||
92
+ data?.error ||
93
+ error.message ||
94
+ "API request failed";
95
+ const code = data?.code;
96
+ throw new errors_1.D3APIError(message, status, code, data);
97
+ }
98
+ else if (error.request) {
99
+ throw new errors_1.DragdropdoError("Network error: No response received from server");
100
+ }
101
+ else {
102
+ throw new errors_1.DragdropdoError(`Request error: ${error.message}`);
103
+ }
104
+ });
105
+ }
106
+ /**
107
+ * Upload a file to D3 storage
108
+ *
109
+ * This method handles the complete upload flow:
110
+ * 1. Request presigned URLs from the API
111
+ * 2. Upload file parts to presigned URLs
112
+ * 3. Return the file key for use in operations
113
+ *
114
+ * @param options - Upload options
115
+ * @returns Promise resolving to upload response with file key
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * // Upload from file path
120
+ * const result = await client.uploadFile({
121
+ * file: '/path/to/file.pdf',
122
+ * fileName: 'document.pdf',
123
+ * mimeType: 'application/pdf',
124
+ * onProgress: (progress) => {
125
+ * console.log(`Upload: ${progress.percentage}%`);
126
+ * }
127
+ * });
128
+ * console.log('File key:', result.fileKey);
129
+ * ```
130
+ */
131
+ async uploadFile(options) {
132
+ const { file, fileName, mimeType, parts, onProgress } = options;
133
+ if (!fileName) {
134
+ throw new errors_1.D3ValidationError("fileName is required");
135
+ }
136
+ // Determine file size
137
+ let fileSize;
138
+ if (typeof file !== "string") {
139
+ throw new errors_1.D3ValidationError("file must be a file path string");
140
+ }
141
+ if (!fs.existsSync(file)) {
142
+ throw new errors_1.D3ValidationError(`File not found: ${file}`);
143
+ }
144
+ const stats = fs.statSync(file);
145
+ fileSize = stats.size;
146
+ // Calculate parts if not provided
147
+ const chunkSize = 5 * 1024 * 1024; // 5MB per part
148
+ const calculatedParts = parts || Math.ceil(fileSize / chunkSize);
149
+ const actualParts = Math.max(1, Math.min(calculatedParts, 100)); // Limit to 100 parts
150
+ // Detect MIME type if not provided
151
+ let detectedMimeType = mimeType;
152
+ if (!detectedMimeType) {
153
+ const ext = path.extname(fileName).toLowerCase();
154
+ detectedMimeType = this.getMimeType(ext) || "application/octet-stream";
155
+ }
156
+ try {
157
+ // Step 1: Request presigned URLs
158
+ const uploadResponse = await this.axiosInstance.post("/v1/biz/initiate-upload", {
159
+ file_name: fileName,
160
+ size: fileSize,
161
+ mime_type: detectedMimeType,
162
+ parts: actualParts,
163
+ });
164
+ const rawData = uploadResponse.data.data;
165
+ // Transform snake_case to camelCase
166
+ const transformed = this.toCamelCase(rawData);
167
+ const fileKey = transformed.fileKey || transformed.file_key;
168
+ const uploadId = transformed.uploadId || transformed.upload_id;
169
+ const presignedUrls = transformed.presignedUrls || transformed.presigned_urls || [];
170
+ const objectName = transformed.objectName || transformed.object_name;
171
+ if (presignedUrls.length !== actualParts) {
172
+ throw new errors_1.D3UploadError(`Mismatch: requested ${actualParts} parts but received ${presignedUrls.length} presigned URLs`);
173
+ }
174
+ if (!uploadId) {
175
+ throw new errors_1.D3UploadError("Upload ID not received from server");
176
+ }
177
+ // Step 2: Upload file parts and capture ETags
178
+ const chunkSizePerPart = Math.ceil(fileSize / actualParts);
179
+ let bytesUploaded = 0;
180
+ const uploadParts = [];
181
+ // Prepare file data for chunking
182
+ // Read entire file into memory for chunking (path-only uploads supported)
183
+ const fileBuffer = fs.readFileSync(file);
184
+ for (let i = 0; i < actualParts; i++) {
185
+ const start = i * chunkSizePerPart;
186
+ const end = Math.min(start + chunkSizePerPart, fileSize);
187
+ const partSize = end - start;
188
+ // Extract chunk from buffer (use subarray to avoid deprecated slice)
189
+ const chunk = fileBuffer.subarray(start, end);
190
+ // Upload chunk and capture ETag from response headers
191
+ const putResponse = await axios_1.default.put(presignedUrls[i], chunk, {
192
+ headers: {
193
+ "Content-Type": detectedMimeType,
194
+ },
195
+ maxContentLength: Infinity,
196
+ maxBodyLength: Infinity,
197
+ });
198
+ // Extract ETag from response (ETag may be quoted, so we'll store it as-is)
199
+ const etag = putResponse.headers.etag || putResponse.headers["ETag"] || "";
200
+ if (!etag) {
201
+ throw new errors_1.D3UploadError(`Failed to get ETag for part ${i + 1}`);
202
+ }
203
+ uploadParts.push({
204
+ etag: etag.replace(/^"|"$/g, ""), // Remove quotes if present
205
+ partNumber: i + 1,
206
+ });
207
+ bytesUploaded += partSize;
208
+ // Report progress
209
+ if (onProgress) {
210
+ onProgress({
211
+ currentPart: i + 1,
212
+ totalParts: actualParts,
213
+ bytesUploaded,
214
+ totalBytes: fileSize,
215
+ percentage: Math.round((bytesUploaded / fileSize) * 100),
216
+ });
217
+ }
218
+ }
219
+ // Step 3: Complete the multipart upload
220
+ try {
221
+ await this.axiosInstance.post("/v1/biz/complete-upload", {
222
+ file_key: fileKey,
223
+ upload_id: uploadId,
224
+ object_name: objectName,
225
+ parts: uploadParts.map((part) => ({
226
+ etag: part.etag,
227
+ part_number: part.partNumber,
228
+ })),
229
+ });
230
+ }
231
+ catch (completeError) {
232
+ if (completeError instanceof errors_1.DragdropdoError ||
233
+ completeError instanceof errors_1.D3APIError) {
234
+ throw new errors_1.D3UploadError(`Failed to complete upload: ${completeError.message}`, completeError);
235
+ }
236
+ const message = completeError?.message || "Unknown error";
237
+ throw new errors_1.D3UploadError(`Failed to complete upload: ${message}`, completeError);
238
+ }
239
+ return {
240
+ file_key: fileKey,
241
+ upload_id: uploadId,
242
+ presigned_urls: presignedUrls,
243
+ object_name: objectName,
244
+ // Provide camelCase aliases for backward compatibility
245
+ fileKey: fileKey,
246
+ uploadId: uploadId,
247
+ presignedUrls: presignedUrls,
248
+ objectName: objectName,
249
+ };
250
+ }
251
+ catch (error) {
252
+ if (error instanceof errors_1.DragdropdoError || error instanceof errors_1.D3APIError) {
253
+ throw error;
254
+ }
255
+ const message = error?.message || "Unknown error";
256
+ throw new errors_1.D3UploadError(`Upload failed: ${message}`, error);
257
+ }
258
+ }
259
+ /**
260
+ * Check if an operation is supported for a file extension
261
+ *
262
+ * @param options - Supported operation options
263
+ * @returns Promise resolving to supported operation response
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * // Check all available actions for PDF
268
+ * const result = await client.checkSupportedOperation({
269
+ * ext: 'pdf'
270
+ * });
271
+ * console.log('Available actions:', result.availableActions);
272
+ *
273
+ * // Check if convert to PNG is supported
274
+ * const result = await client.checkSupportedOperation({
275
+ * ext: 'pdf',
276
+ * action: 'convert',
277
+ * parameters: { convert_to: 'png' }
278
+ * });
279
+ * console.log('Supported:', result.supported);
280
+ *
281
+ * // Get available compression levels
282
+ * const result = await client.checkSupportedOperation({
283
+ * ext: 'pdf',
284
+ * action: 'compress'
285
+ * });
286
+ * console.log('Compression levels:', result.parameters?.compression_value);
287
+ * ```
288
+ */
289
+ async checkSupportedOperation(options) {
290
+ if (!options.ext) {
291
+ throw new errors_1.D3ValidationError("Extension (ext) is required");
292
+ }
293
+ try {
294
+ const response = await this.axiosInstance.post("/v1/biz/supported-operation", {
295
+ ext: options.ext,
296
+ action: options.action,
297
+ parameters: options.parameters,
298
+ });
299
+ return response.data.data;
300
+ }
301
+ catch (error) {
302
+ if (error instanceof errors_1.DragdropdoError || error instanceof errors_1.D3APIError) {
303
+ throw error;
304
+ }
305
+ const message = error?.message || "Unknown error";
306
+ throw new errors_1.DragdropdoError(`Failed to check supported operation: ${message}`, undefined, undefined, error);
307
+ }
308
+ }
309
+ /**
310
+ * Create a file operation (convert, compress, merge, zip, etc.)
311
+ *
312
+ * @param options - Operation options
313
+ * @returns Promise resolving to operation response with main task ID
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * // Convert PDF to PNG
318
+ * const result = await client.createOperation({
319
+ * action: 'convert',
320
+ * fileKeys: ['file-key-123'],
321
+ * parameters: { convert_to: 'png' }
322
+ * });
323
+ *
324
+ * // Compress PDF
325
+ * const result = await client.createOperation({
326
+ * action: 'compress',
327
+ * fileKeys: ['file-key-123'],
328
+ * parameters: { compression_value: 'recommended' }
329
+ * });
330
+ *
331
+ * // Merge multiple PDFs
332
+ * const result = await client.createOperation({
333
+ * action: 'merge',
334
+ * fileKeys: ['file-key-1', 'file-key-2', 'file-key-3']
335
+ * });
336
+ *
337
+ * // Lock PDF with password
338
+ * const result = await client.createOperation({
339
+ * action: 'lock',
340
+ * fileKeys: ['file-key-123'],
341
+ * parameters: { password: 'secure-password' }
342
+ * });
343
+ * ```
344
+ */
345
+ async createOperation(options) {
346
+ if (!options.action) {
347
+ throw new errors_1.D3ValidationError("Action is required");
348
+ }
349
+ if (!options.fileKeys || options.fileKeys.length === 0) {
350
+ throw new errors_1.D3ValidationError("At least one file key is required");
351
+ }
352
+ try {
353
+ const response = await this.axiosInstance.post("/v1/biz/do", {
354
+ action: options.action,
355
+ file_keys: options.fileKeys,
356
+ parameters: options.parameters,
357
+ notes: options.notes,
358
+ });
359
+ const rawData = response.data.data;
360
+ // Transform snake_case to camelCase
361
+ const transformed = this.toCamelCase(rawData);
362
+ return {
363
+ mainTaskId: transformed.mainTaskId || transformed.main_task_id,
364
+ };
365
+ }
366
+ catch (error) {
367
+ if (error instanceof errors_1.DragdropdoError || error instanceof errors_1.D3APIError) {
368
+ throw error;
369
+ }
370
+ const message = error?.message || "Unknown error";
371
+ throw new errors_1.DragdropdoError(`Failed to create operation: ${message}`, undefined, undefined, error);
372
+ }
373
+ }
374
+ /**
375
+ * Convenience methods for specific operations
376
+ */
377
+ /**
378
+ * Convert files to a different format
379
+ */
380
+ async convert(fileKeys, convertTo, notes) {
381
+ return this.createOperation({
382
+ action: "convert",
383
+ fileKeys,
384
+ parameters: { convert_to: convertTo },
385
+ notes,
386
+ });
387
+ }
388
+ /**
389
+ * Compress files
390
+ */
391
+ async compress(fileKeys, compressionValue = "recommended", notes) {
392
+ return this.createOperation({
393
+ action: "compress",
394
+ fileKeys,
395
+ parameters: { compression_value: compressionValue },
396
+ notes,
397
+ });
398
+ }
399
+ /**
400
+ * Merge multiple files
401
+ */
402
+ async merge(fileKeys, notes) {
403
+ return this.createOperation({
404
+ action: "merge",
405
+ fileKeys,
406
+ notes,
407
+ });
408
+ }
409
+ /**
410
+ * Create a ZIP archive from files
411
+ */
412
+ async zip(fileKeys, notes) {
413
+ return this.createOperation({
414
+ action: "zip",
415
+ fileKeys,
416
+ notes,
417
+ });
418
+ }
419
+ /**
420
+ * Share files (generate shareable links)
421
+ */
422
+ async share(fileKeys, notes) {
423
+ return this.createOperation({
424
+ action: "share",
425
+ fileKeys,
426
+ notes,
427
+ });
428
+ }
429
+ /**
430
+ * Lock PDF with password
431
+ */
432
+ async lockPdf(fileKeys, password, notes) {
433
+ return this.createOperation({
434
+ action: "lock",
435
+ fileKeys,
436
+ parameters: { password },
437
+ notes,
438
+ });
439
+ }
440
+ /**
441
+ * Unlock PDF with password
442
+ */
443
+ async unlockPdf(fileKeys, password, notes) {
444
+ return this.createOperation({
445
+ action: "unlock",
446
+ fileKeys,
447
+ parameters: { password },
448
+ notes,
449
+ });
450
+ }
451
+ /**
452
+ * Reset PDF password
453
+ */
454
+ async resetPdfPassword(fileKeys, oldPassword, newPassword, notes) {
455
+ return this.createOperation({
456
+ action: "reset_password",
457
+ fileKeys,
458
+ parameters: {
459
+ old_password: oldPassword,
460
+ new_password: newPassword,
461
+ },
462
+ notes,
463
+ });
464
+ }
465
+ /**
466
+ * Get operation status
467
+ *
468
+ * @param options - Status options
469
+ * @returns Promise resolving to status response
470
+ *
471
+ * @example
472
+ * ```typescript
473
+ * // Get main task status
474
+ * const status = await client.getStatus({
475
+ * mainTaskId: 'task-123'
476
+ * });
477
+ *
478
+ * // Get specific file task status
479
+ * const status = await client.getStatus({
480
+ * mainTaskId: 'task-123',
481
+ * fileTaskId: 'file-task-456'
482
+ * });
483
+ * ```
484
+ */
485
+ async getStatus(options) {
486
+ if (!options.mainTaskId) {
487
+ throw new errors_1.D3ValidationError("mainTaskId is required");
488
+ }
489
+ try {
490
+ let url = `/v1/biz/status/${options.mainTaskId}`;
491
+ if (options.fileTaskId) {
492
+ url += `/${options.fileTaskId}`;
493
+ }
494
+ const response = await this.axiosInstance.get(url);
495
+ const rawData = response.data.data;
496
+ // Transform snake_case to camelCase
497
+ const transformed = this.toCamelCase(rawData);
498
+ return {
499
+ operationStatus: transformed.operationStatus || transformed.operation_status,
500
+ filesData: (transformed.filesData || transformed.files_data || []).map((file) => ({
501
+ fileKey: file.fileKey || file.file_key,
502
+ status: file.status,
503
+ downloadLink: file.downloadLink || file.download_link,
504
+ errorCode: file.errorCode || file.error_code,
505
+ errorMessage: file.errorMessage || file.error_message,
506
+ })),
507
+ };
508
+ }
509
+ catch (error) {
510
+ if (error instanceof errors_1.DragdropdoError || error instanceof errors_1.D3APIError) {
511
+ throw error;
512
+ }
513
+ const message = error?.message || "Unknown error";
514
+ throw new errors_1.DragdropdoError(`Failed to get status: ${message}`, undefined, undefined, error);
515
+ }
516
+ }
517
+ /**
518
+ * Poll operation status until completion or failure
519
+ *
520
+ * @param options - Poll status options
521
+ * @returns Promise resolving to final status response
522
+ *
523
+ * @example
524
+ * ```typescript
525
+ * const status = await client.pollStatus({
526
+ * mainTaskId: 'task-123',
527
+ * interval: 2000, // Check every 2 seconds
528
+ * timeout: 300000, // 5 minutes max
529
+ * onUpdate: (status) => {
530
+ * console.log('Status:', status.operationStatus);
531
+ * }
532
+ * });
533
+ *
534
+ * if (status.operationStatus === 'completed') {
535
+ * console.log('Download links:', status.filesData.map(f => f.downloadLink));
536
+ * }
537
+ * ```
538
+ */
539
+ async pollStatus(options) {
540
+ const { mainTaskId, fileTaskId, interval = 2000, timeout = 300000, onUpdate, } = options;
541
+ const startTime = Date.now();
542
+ return new Promise((resolve, reject) => {
543
+ const poll = async () => {
544
+ try {
545
+ // Check timeout
546
+ if (Date.now() - startTime > timeout) {
547
+ reject(new errors_1.D3TimeoutError(`Polling timed out after ${timeout}ms`));
548
+ return;
549
+ }
550
+ // Get status
551
+ const status = await this.getStatus({ mainTaskId, fileTaskId });
552
+ // Call update callback
553
+ if (onUpdate) {
554
+ onUpdate(status);
555
+ }
556
+ // Check if completed or failed
557
+ if (status.operationStatus === "completed" ||
558
+ status.operationStatus === "failed") {
559
+ resolve(status);
560
+ return;
561
+ }
562
+ // Continue polling
563
+ // setTimeout is available globally in Node.js
564
+ // @ts-ignore - setTimeout is available in Node.js runtime
565
+ setTimeout(poll, interval);
566
+ }
567
+ catch (error) {
568
+ reject(error);
569
+ }
570
+ };
571
+ poll();
572
+ });
573
+ }
574
+ /**
575
+ * Convert snake_case object keys to camelCase
576
+ */
577
+ toCamelCase(obj) {
578
+ if (obj === null || obj === undefined) {
579
+ return obj;
580
+ }
581
+ if (Array.isArray(obj)) {
582
+ return obj.map((item) => this.toCamelCase(item));
583
+ }
584
+ if (typeof obj === "object") {
585
+ const camelObj = {};
586
+ for (const key in obj) {
587
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
588
+ const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
589
+ camelObj[camelKey] = this.toCamelCase(obj[key]);
590
+ // Also keep original key for backward compatibility
591
+ camelObj[key] = obj[key];
592
+ }
593
+ }
594
+ return camelObj;
595
+ }
596
+ return obj;
597
+ }
598
+ /**
599
+ * Get MIME type from file extension
600
+ */
601
+ getMimeType(ext) {
602
+ const mimeTypes = {
603
+ ".pdf": "application/pdf",
604
+ ".jpg": "image/jpeg",
605
+ ".jpeg": "image/jpeg",
606
+ ".png": "image/png",
607
+ ".gif": "image/gif",
608
+ ".webp": "image/webp",
609
+ ".doc": "application/msword",
610
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
611
+ ".xls": "application/vnd.ms-excel",
612
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
613
+ ".zip": "application/zip",
614
+ ".txt": "text/plain",
615
+ ".mp4": "video/mp4",
616
+ ".mp3": "audio/mpeg",
617
+ };
618
+ return mimeTypes[ext.toLowerCase()] || null;
619
+ }
620
+ }
621
+ exports.Dragdropdo = Dragdropdo;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Custom error classes for dragdropdo.com Business API Client
3
+ */
4
+ import { D3Error } from "./types";
5
+ export declare class DragdropdoError extends Error implements D3Error {
6
+ statusCode?: number;
7
+ code?: number;
8
+ details?: any;
9
+ constructor(message: string, statusCode?: number, code?: number, details?: any);
10
+ }
11
+ export declare class D3APIError extends DragdropdoError {
12
+ constructor(message: string, statusCode: number, code?: number, details?: any);
13
+ }
14
+ export declare class D3ValidationError extends DragdropdoError {
15
+ constructor(message: string, details?: any);
16
+ }
17
+ export declare class D3UploadError extends DragdropdoError {
18
+ constructor(message: string, details?: any);
19
+ }
20
+ export declare class D3TimeoutError extends DragdropdoError {
21
+ constructor(message?: string);
22
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Custom error classes for dragdropdo.com Business API Client
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.D3TimeoutError = exports.D3UploadError = exports.D3ValidationError = exports.D3APIError = exports.DragdropdoError = void 0;
7
+ class DragdropdoError extends Error {
8
+ constructor(message, statusCode, code, details) {
9
+ super(message);
10
+ this.name = "DragdropdoError";
11
+ this.statusCode = statusCode;
12
+ this.code = code;
13
+ this.details = details;
14
+ // Capture stack trace if available (Node.js)
15
+ if (typeof Error.captureStackTrace === "function") {
16
+ Error.captureStackTrace(this, this.constructor);
17
+ }
18
+ }
19
+ }
20
+ exports.DragdropdoError = DragdropdoError;
21
+ class D3APIError extends DragdropdoError {
22
+ constructor(message, statusCode, code, details) {
23
+ super(message, statusCode, code, details);
24
+ this.name = "D3APIError";
25
+ }
26
+ }
27
+ exports.D3APIError = D3APIError;
28
+ class D3ValidationError extends DragdropdoError {
29
+ constructor(message, details) {
30
+ super(message, 400, undefined, details);
31
+ this.name = "D3ValidationError";
32
+ }
33
+ }
34
+ exports.D3ValidationError = D3ValidationError;
35
+ class D3UploadError extends DragdropdoError {
36
+ constructor(message, details) {
37
+ super(message, undefined, undefined, details);
38
+ this.name = "D3UploadError";
39
+ }
40
+ }
41
+ exports.D3UploadError = D3UploadError;
42
+ class D3TimeoutError extends DragdropdoError {
43
+ constructor(message = "Operation timed out") {
44
+ super(message);
45
+ this.name = "D3TimeoutError";
46
+ }
47
+ }
48
+ exports.D3TimeoutError = D3TimeoutError;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * DragDropDo SDK - Node.js Client Library
3
+ *
4
+ * Official Node.js client for the dragdropdo.com Business API
5
+ */
6
+ export { Dragdropdo } from "./client";
7
+ export * from "./types";
8
+ export * from "./errors";
9
+ export { Dragdropdo as default } from "./client";