@adbjs/sdk 1.0.0 → 2.0.1

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,17 +2,18 @@
2
2
 
3
3
  Modern TypeScript SDK for the AllDebrid API v4.1.
4
4
 
5
- ## Features
5
+ ## Features
6
6
 
7
- - **TypeScript-first** - Full type safety with auto-generated types from OpenAPI v4.1 spec
7
+ - 🎯 **TypeScript-first** - Full type safety with auto-generated types from OpenAPI v4.1 spec
8
8
  - 🚀 **Modern** - Built with wretch, ESM + CJS support
9
9
  - 📦 **Tree-shakeable** - Import only what you need
10
10
  - 🔄 **Auto-retry** - Built-in retry logic with configurable options
11
- - 🎯 **Type-safe errors** - Typed error classes for better error handling
11
+ - 🛡️ **Type-safe errors** - Typed error classes for better error handling
12
12
  - 📝 **Fully documented** - JSDoc comments with examples
13
13
  - ⚡ **API v4.1 optimized** - Designed and optimized for AllDebrid API v4.1
14
+ - 💡 **Minimal footprint** - Only one runtime dependency (wretch)
14
15
 
15
- ## Installation
16
+ ## 📦 Installation
16
17
 
17
18
  ```bash
18
19
  npm install @adbjs/sdk
@@ -22,7 +23,7 @@ pnpm add @adbjs/sdk
22
23
  yarn add @adbjs/sdk
23
24
  ```
24
25
 
25
- ## Quick Start
26
+ ## 🚀 Quick Start
26
27
 
27
28
  ```typescript
28
29
  import { AllDebridClient } from '@adbjs/sdk'
@@ -45,14 +46,14 @@ const magnet = await client.magnet.upload('magnet:?xt=urn:btih:...')
45
46
  console.log('Magnet ID:', magnet.magnets[0].id)
46
47
  ```
47
48
 
48
- ## API Reference
49
+ ## 📖 API Reference
49
50
 
50
51
  ### Client Configuration
51
52
 
52
53
  ```typescript
53
54
  const client = new AllDebridClient({
54
55
  apiKey: string // Required: Your AllDebrid API key
55
- agent?: string // Optional: User agent (default: '@alldebrid/sdk')
56
+ agent?: string // Optional: User agent (default: '@adbjs/sdk')
56
57
  baseUrl?: string // Optional: API base URL
57
58
  timeout?: number // Optional: Request timeout in ms (default: 30000)
58
59
  retry?: boolean // Optional: Enable auto-retry (default: true)
@@ -171,10 +172,8 @@ counter = firstCall.counter // Important: Use the returned counter value
171
172
  const secondCall = await client.magnet.statusLive({ session, counter })
172
173
  console.log('Delta sync (only changes):', secondCall.magnets)
173
174
 
174
- // Live mode can also track a specific magnet
175
+ // Update counter for subsequent calls
175
176
  counter = secondCall.counter
176
- const specificMagnet = await client.magnet.statusLive({ session, counter }, 123)
177
- console.log('Changes for magnet 123:', specificMagnet.magnets)
178
177
 
179
178
  // ===== Magnet management =====
180
179
 
@@ -192,27 +191,16 @@ files?.forEach((file) => {
192
191
 
193
192
  // ===== Watch: Monitor magnet progress with automatic polling =====
194
193
 
195
- // Standard mode: Full status check on each poll
194
+ // Watch a magnet until it's ready
196
195
  await client.magnet.watch(123, {
197
196
  interval: 3000, // Check every 3 seconds
198
- maxAttempts: 30, // Stop after 30 attempts
197
+ maxAttempts: 30, // Stop after 30 attempts (0 = infinite)
199
198
  stopOnStatus: 'Ready', // Stop when magnet is ready
200
199
  onUpdate: (status) => {
201
200
  const magnet = status.magnets[0]
202
201
  console.log(`Progress: ${magnet?.status} - ${magnet?.downloaded || 0}%`)
203
202
  },
204
203
  })
205
-
206
- // Live mode: Delta sync for reduced bandwidth (recommended for long-running monitors)
207
- await client.magnet.watch(123, {
208
- useLiveMode: true, // Enable live mode
209
- interval: 2000, // Check every 2 seconds
210
- maxAttempts: 0, // 0 = infinite polling
211
- onUpdate: (status) => {
212
- // Only called when the magnet status changes
213
- console.log('Magnet updated:', status.magnets[0])
214
- },
215
- })
216
204
  ```
217
205
 
218
206
  ### Host Resource
@@ -272,7 +260,7 @@ const newVouchers = await client.voucher.generateVouchers(10, 30)
272
260
  console.log('Generated vouchers:', newVouchers?.codes)
273
261
  ```
274
262
 
275
- ## Error Handling
263
+ ## 🛡️ Error Handling
276
264
 
277
265
  The SDK provides typed error classes for better error handling:
278
266
 
@@ -298,7 +286,7 @@ try {
298
286
  }
299
287
  ```
300
288
 
301
- ## Type Safety
289
+ ## 🎯 Type Safety
302
290
 
303
291
  All responses are fully typed using types generated from the official AllDebrid API v4.1 OpenAPI specification:
304
292
 
@@ -306,7 +294,7 @@ All responses are fully typed using types generated from the official AllDebrid
306
294
  import type { GetLinkUnlockResponse, GetMagnetStatusResponse, GetUserResponse } from '@adbjs/sdk'
307
295
  ```
308
296
 
309
- ## Development
297
+ ## 🏗️ Development
310
298
 
311
299
  ```bash
312
300
  # Install dependencies
@@ -325,11 +313,11 @@ pnpm test
325
313
  pnpm typecheck
326
314
  ```
327
315
 
328
- ## License
316
+ ## 📝 License
329
317
 
330
318
  MIT
331
319
 
332
- ## Links
320
+ ## 🔗 Links
333
321
 
334
322
  - [AllDebrid API Documentation](https://docs.alldebrid.com/)
335
323
  - [GitHub Repository](https://github.com/Trisard/alldebrid-ts)
package/dist/index.cjs CHANGED
@@ -159,11 +159,11 @@ var LinkResource = class extends BaseResource {
159
159
  *
160
160
  * @example
161
161
  * ```ts
162
- * const info = await client.link.infos('https://example.com/file.zip')
163
- * console.log(info)
162
+ * const data = await client.link.infos('https://example.com/file.zip')
163
+ * console.log(data.infos)
164
164
  *
165
165
  * // With password
166
- * const protectedInfo = await client.link.infos(
166
+ * const protectedData = await client.link.infos(
167
167
  * 'https://example.com/protected.zip',
168
168
  * 'mypassword'
169
169
  * )
@@ -172,12 +172,7 @@ var LinkResource = class extends BaseResource {
172
172
  async infos(links, password) {
173
173
  const linksArray = Array.isArray(links) ? links : [links];
174
174
  const params = password ? { password } : void 0;
175
- const data = await this.post(
176
- "/link/infos",
177
- { "link[]": linksArray },
178
- params
179
- );
180
- return data?.infos;
175
+ return this.post("/link/infos", { "link[]": linksArray }, params);
181
176
  }
182
177
  /**
183
178
  * Extract links from redirectors/link protectors
@@ -186,14 +181,14 @@ var LinkResource = class extends BaseResource {
186
181
  *
187
182
  * @example
188
183
  * ```ts
189
- * const links = await client.link.redirector('https://linkprotector.com/abc123')
184
+ * const data = await client.link.redirector('https://linkprotector.com/abc123')
185
+ * console.log(data.links)
190
186
  * ```
191
187
  */
192
188
  async redirector(link) {
193
- const data = await this.post("/link/redirector", {
189
+ return this.post("/link/redirector", {
194
190
  link
195
191
  });
196
- return data?.links;
197
192
  }
198
193
  /**
199
194
  * Unlock a download link
@@ -363,16 +358,38 @@ var MagnetResource = class extends BaseResource {
363
358
  return this.post("/magnet/status", body);
364
359
  }
365
360
  /**
366
- * Get magnet status using live mode for reduced bandwidth consumption
361
+ * Get magnet status using live mode for bandwidth-optimized delta synchronization
362
+ *
363
+ * Live mode is designed for monitoring multiple magnets efficiently by only transmitting
364
+ * changes between polling intervals, drastically reducing bandwidth usage for dashboards
365
+ * and real-time monitoring applications.
366
+ *
367
+ * ## How it works
368
+ *
369
+ * 1. **Session initialization**: Generate a random session ID and start with counter = 0
370
+ * 2. **First call (fullsync)**: Returns ALL magnets with `fullsync: true`
371
+ * 3. **Update counter**: Use the `counter` value returned by the API for the next call
372
+ * 4. **Subsequent calls (delta)**: Returns ONLY magnets that changed since last call
373
+ * 5. **Repeat**: Keep calling with updated counter to receive only deltas
374
+ *
375
+ * ## When to use
376
+ *
377
+ * - ✅ Monitoring multiple active magnets simultaneously
378
+ * - ✅ Building real-time dashboards
379
+ * - ✅ High-frequency polling scenarios (every few seconds)
380
+ * - ❌ Watching a single specific magnet (use `watch()` instead)
367
381
  *
368
- * Live mode uses delta synchronization - only changes since the last call are transmitted.
369
- * On the first call (counter=0), all data is returned with `fullsync: true`.
370
- * Subsequent calls return only modifications.
382
+ * ## Important notes
371
383
  *
372
- * @param options - Live mode options
373
- * @param options.session - Session ID (generate once per session and reuse)
374
- * @param options.counter - Synchronization counter (start at 0, use returned counter for next call)
375
- * @param id - Optional magnet ID to filter a specific magnet
384
+ * - **Don't use the `id` parameter**: Passing an ID defeats the purpose of live mode
385
+ * as it disables delta sync and behaves like a regular `status()` call
386
+ * - **Session persistence**: Keep the same session ID for the entire monitoring session
387
+ * - **Counter tracking**: Always update the counter with the value returned by the API
388
+ * - **Empty deltas**: When no magnets changed, `magnets` will be an empty array
389
+ *
390
+ * @param options - Live mode session options
391
+ * @param options.session - Unique session ID (generate once: `Math.floor(Math.random() * 1000000)`)
392
+ * @param options.counter - Sync counter (start at 0, then use value from previous API response)
376
393
  *
377
394
  * @example
378
395
  * ```ts
@@ -380,34 +397,64 @@ var MagnetResource = class extends BaseResource {
380
397
  * const session = Math.floor(Math.random() * 1000000)
381
398
  * let counter = 0
382
399
  *
383
- * // First call - full sync
400
+ * // First call - returns all magnets (fullsync: true)
384
401
  * const firstCall = await client.magnet.statusLive({ session, counter })
385
402
  * console.log('Full sync:', firstCall.fullsync) // true
386
- * console.log('All magnets:', firstCall.magnets)
387
- *
388
- * // Update counter with value returned by API
389
- * counter = firstCall.counter
403
+ * console.log('All magnets:', firstCall.magnets) // Array of all magnets
404
+ * counter = firstCall.counter // Update counter for next call
390
405
  *
391
- * // Second call - only changes
406
+ * // Second call - returns only magnets that changed
407
+ * await new Promise(resolve => setTimeout(resolve, 3000)) // Wait 3 seconds
392
408
  * const secondCall = await client.magnet.statusLive({ session, counter })
393
- * console.log('Delta sync:', secondCall.magnets) // Only modified magnets
409
+ * console.log('Delta sync:', secondCall.magnets) // Only changed magnets
410
+ * counter = secondCall.counter
411
+ *
412
+ * // Example: Monitor all magnets until none are active
413
+ * const activeMagnets = new Map()
414
+ *
415
+ * while (true) {
416
+ * const response = await client.magnet.statusLive({ session, counter })
417
+ * counter = response.counter ?? counter
418
+ *
419
+ * // Update our local state with changes
420
+ * if (response.fullsync) {
421
+ * activeMagnets.clear()
422
+ * response.magnets?.forEach(m => activeMagnets.set(m.id, m))
423
+ * } else {
424
+ * response.magnets?.forEach(m => {
425
+ * if (m.status === 'Ready' || m.status === 'Error' || m.status === 'Expired') {
426
+ * activeMagnets.delete(m.id)
427
+ * } else {
428
+ * activeMagnets.set(m.id, m)
429
+ * }
430
+ * })
431
+ * }
432
+ *
433
+ * // Display current state
434
+ * console.log(`Active downloads: ${activeMagnets.size}`)
435
+ * activeMagnets.forEach(m => {
436
+ * console.log(` ${m.filename}: ${m.status} - ${m.downloaded}/${m.size} bytes`)
437
+ * })
438
+ *
439
+ * // Stop when no more active magnets
440
+ * if (activeMagnets.size === 0) {
441
+ * console.log('All downloads completed!')
442
+ * break
443
+ * }
394
444
  *
395
- * // Filter specific magnet in live mode
396
- * const magnetLive = await client.magnet.statusLive({ session, counter }, 123)
445
+ * await new Promise(resolve => setTimeout(resolve, 3000))
446
+ * }
397
447
  * ```
398
448
  *
399
449
  * @remarks
400
- * This is ideal for real-time dashboards or frequent polling scenarios
401
- * as it significantly reduces bandwidth usage by transmitting only changes.
450
+ * This method is ideal for scenarios where you're monitoring multiple magnets and want
451
+ * to minimize bandwidth. For simple single-magnet monitoring, use `watch()` instead.
402
452
  */
403
- async statusLive(options, id) {
453
+ async statusLive(options) {
404
454
  const body = {
405
455
  session: options.session,
406
456
  counter: options.counter
407
457
  };
408
- if (id !== void 0) {
409
- body.id = id;
410
- }
411
458
  return this.post("/magnet/status", body);
412
459
  }
413
460
  /**
@@ -452,9 +499,9 @@ var MagnetResource = class extends BaseResource {
452
499
  *
453
500
  * @example
454
501
  * ```ts
455
- * const files = await client.magnet.files(123)
456
- * files?.forEach(file => {
457
- * console.log(file.filename, file.link)
502
+ * const data = await client.magnet.files(123)
503
+ * data?.magnets?.forEach(magnet => {
504
+ * console.log(magnet.filename, magnet.files)
458
505
  * })
459
506
  * ```
460
507
  *
@@ -468,56 +515,40 @@ var MagnetResource = class extends BaseResource {
468
515
  for (const id of idsArray) {
469
516
  formData.append("id[]", String(id));
470
517
  }
471
- const data = await this.postFormData("/magnet/files", formData);
472
- return data?.magnets;
518
+ return this.postFormData("/magnet/files", formData);
473
519
  }
474
520
  /**
475
521
  * Watch a magnet's status with automatic polling
476
522
  *
523
+ * This is a simple helper that polls the status of a specific magnet until it reaches
524
+ * a target status (default: 'Ready'). For advanced use cases with multiple magnets
525
+ * or bandwidth optimization, use `statusLive()` directly instead.
526
+ *
477
527
  * @param id - The magnet ID to watch
478
528
  * @param options - Watch options
479
529
  * @param options.interval - Polling interval in milliseconds (default: 3000)
480
530
  * @param options.maxAttempts - Maximum polling attempts, 0 for infinite (default: 0)
481
531
  * @param options.onUpdate - Callback called on each status update
482
532
  * @param options.stopOnStatus - Stop when magnet reaches this status (default: 'Ready')
483
- * @param options.useLiveMode - Use live mode for reduced bandwidth (default: false)
484
533
  *
485
534
  * @example
486
535
  * ```ts
487
- * // Standard mode
488
536
  * await client.magnet.watch(123, {
489
537
  * onUpdate: (status) => console.log('Status:', status.magnets[0]?.status),
490
538
  * stopOnStatus: 'Ready'
491
539
  * })
492
- *
493
- * // Live mode for reduced bandwidth
494
- * await client.magnet.watch(123, {
495
- * useLiveMode: true,
496
- * interval: 2000,
497
- * onUpdate: (status) => console.log('Update:', status)
498
- * })
499
540
  * ```
541
+ *
542
+ * @remarks
543
+ * For monitoring multiple magnets efficiently, use `statusLive()` directly.
544
+ * See the `statusLive()` documentation for details on delta synchronization.
500
545
  */
501
546
  async watch(id, options = {}) {
502
- const {
503
- interval = 3e3,
504
- maxAttempts = 0,
505
- onUpdate,
506
- stopOnStatus = "Ready",
507
- useLiveMode = false
508
- } = options;
547
+ const { interval = 3e3, maxAttempts = 0, onUpdate, stopOnStatus = "Ready" } = options;
509
548
  let attempt = 0;
510
- let session;
511
- let counter = 0;
512
- if (useLiveMode) {
513
- session = Math.floor(Math.random() * 1e6);
514
- }
515
549
  while (maxAttempts === 0 || attempt < maxAttempts) {
516
550
  attempt++;
517
- const status = useLiveMode && session !== void 0 ? await this.statusLive({ session, counter }, id) : await this.status(id);
518
- if (useLiveMode && status?.counter !== void 0) {
519
- counter = status.counter;
520
- }
551
+ const status = await this.status(id);
521
552
  onUpdate?.(status);
522
553
  const magnet = status?.magnets?.[0];
523
554
  if (magnet?.status === stopOnStatus) {
@@ -643,13 +674,12 @@ var UserResource = class extends BaseResource {
643
674
  *
644
675
  * @example
645
676
  * ```ts
646
- * const user = await client.user.getInfo()
647
- * console.log(user.username, user.isPremium)
677
+ * const data = await client.user.getInfo()
678
+ * console.log(data.user.username, data.user.isPremium)
648
679
  * ```
649
680
  */
650
681
  async getInfo() {
651
- const data = await this.get("/user");
652
- return data?.user;
682
+ return this.get("/user");
653
683
  }
654
684
  /**
655
685
  * Get available hosts for the current user based on their subscription
@@ -882,7 +912,7 @@ var VoucherResource = class extends BaseResource {
882
912
 
883
913
  // src/client.ts
884
914
  var DEFAULT_BASE_URL = "https://api.alldebrid.com/v4.1";
885
- var DEFAULT_AGENT = "@alldebrid/sdk";
915
+ var DEFAULT_AGENT = "@adbjs/sdk";
886
916
  var DEFAULT_TIMEOUT = 3e4;
887
917
  var DEFAULT_MAX_RETRIES = 3;
888
918
  var AllDebridClient = class {