ytdlp-react-native 1.0.0 → 1.1.0-beta.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +54 -1
  2. package/README.md +422 -267
  3. package/android/src/main/AndroidManifest.xml +20 -1
  4. package/android/src/main/java/expo/modules/ytdlp/ExpoYtDlpModule.kt +8 -0
  5. package/android/src/main/java/expo/modules/ytdlp/YtDlpDownloadManager.kt +177 -16
  6. package/android/src/main/java/expo/modules/ytdlp/YtDlpEngine.kt +35 -4
  7. package/android/src/main/java/expo/modules/ytdlp/YtDlpForegroundService.kt +241 -0
  8. package/android/src/main/java/expo/modules/ytdlp/YtDlpTask.kt +44 -2
  9. package/build/ExpoYtDlpModule.d.ts +2 -0
  10. package/build/ExpoYtDlpModule.d.ts.map +1 -1
  11. package/build/ExpoYtDlpModule.js.map +1 -1
  12. package/build/YtDlp.d.ts +10 -0
  13. package/build/YtDlp.d.ts.map +1 -1
  14. package/build/YtDlp.js +22 -77
  15. package/build/YtDlp.js.map +1 -1
  16. package/build/constants.d.ts +1 -4
  17. package/build/constants.d.ts.map +1 -1
  18. package/build/constants.js +2 -1
  19. package/build/constants.js.map +1 -1
  20. package/build/downloadTask.d.ts +2 -0
  21. package/build/downloadTask.d.ts.map +1 -1
  22. package/build/downloadTask.js +7 -0
  23. package/build/downloadTask.js.map +1 -1
  24. package/build/errors.js +3 -3
  25. package/build/errors.js.map +1 -1
  26. package/build/index.d.ts +3 -1
  27. package/build/index.d.ts.map +1 -1
  28. package/build/index.js +3 -1
  29. package/build/index.js.map +1 -1
  30. package/build/mappers.js +3 -2
  31. package/build/mappers.js.map +1 -1
  32. package/build/serializers.d.ts +5 -0
  33. package/build/serializers.d.ts.map +1 -0
  34. package/build/serializers.js +96 -0
  35. package/build/serializers.js.map +1 -0
  36. package/build/types.d.ts +39 -1
  37. package/build/types.d.ts.map +1 -1
  38. package/build/types.js.map +1 -1
  39. package/package.json +7 -5
  40. package/src/ExpoYtDlpModule.ts +2 -0
  41. package/src/YtDlp.ts +21 -57
  42. package/src/__tests__/errors.test.ts +117 -0
  43. package/src/__tests__/mappers.test.ts +167 -0
  44. package/src/__tests__/serializers.test.ts +72 -0
  45. package/src/constants.ts +3 -1
  46. package/src/downloadTask.ts +9 -0
  47. package/src/errors.ts +3 -3
  48. package/src/index.ts +3 -1
  49. package/src/mappers.ts +3 -2
  50. package/src/serializers.ts +78 -0
  51. package/src/types.ts +47 -1
@@ -10,6 +10,7 @@ internal enum class YtDlpStatus {
10
10
  EXTRACTING,
11
11
  DOWNLOADING,
12
12
  PROCESSING,
13
+ PAUSED,
13
14
  COMPLETED,
14
15
  CANCELLED,
15
16
  FAILED,
@@ -46,6 +47,13 @@ internal class YtDlpTask(
46
47
  var startTime: Long = System.currentTimeMillis()
47
48
 
48
49
  private val cancelRequested = AtomicBoolean(false)
50
+ private val pauseRequested = AtomicBoolean(false)
51
+
52
+ /** Increments on every run (initial start and each resume); see AGENTS.md §4 lifecycle. */
53
+ @Volatile
54
+ var runGeneration = 0
55
+ private set
56
+
49
57
  internal val snapshot = ProgressSnapshot()
50
58
  private val lastEmit = AtomicLong(0L)
51
59
 
@@ -53,6 +61,35 @@ internal class YtDlpTask(
53
61
 
54
62
  fun requestCancel(): Boolean = cancelRequested.compareAndSet(false, true)
55
63
 
64
+ fun isPauseRequested(): Boolean = pauseRequested.get()
65
+
66
+ /** Accepts the pause only while a run is actually in flight (not terminal, not already paused). */
67
+ fun requestPause(): Boolean {
68
+ val current = status
69
+ if (current == YtDlpStatus.COMPLETED || current == YtDlpStatus.CANCELLED ||
70
+ current == YtDlpStatus.FAILED || current == YtDlpStatus.PAUSED
71
+ ) {
72
+ return false
73
+ }
74
+ return pauseRequested.compareAndSet(false, true)
75
+ }
76
+
77
+ /**
78
+ * Prepares a fresh run (initial start or resume): bumps the generation so
79
+ * any stale runner thread stops touching the task, clears pause/cancel
80
+ * requests and error state, and restarts the completion clock.
81
+ */
82
+ @Synchronized
83
+ fun beginRun(): Int {
84
+ runGeneration += 1
85
+ pauseRequested.set(false)
86
+ cancelRequested.set(false)
87
+ errorCode = null
88
+ errorMessage = null
89
+ startTime = System.currentTimeMillis()
90
+ return runGeneration
91
+ }
92
+
56
93
  @Synchronized
57
94
  fun setStatus(newStatus: YtDlpStatus) {
58
95
  if (status == YtDlpStatus.COMPLETED || status == YtDlpStatus.CANCELLED || status == YtDlpStatus.FAILED) return
@@ -70,7 +107,7 @@ internal class YtDlpTask(
70
107
  etaSeconds: Long,
71
108
  filename: String,
72
109
  ) {
73
- if (cancelRequested.get()) return
110
+ if (cancelRequested.get() || pauseRequested.get()) return
74
111
  snapshot.update(downloadedBytes, totalBytes, speedBytesPerSecond, etaSeconds, filename)
75
112
  when {
76
113
  status == YtDlpStatus.QUEUED -> setStatus(YtDlpStatus.EXTRACTING)
@@ -94,6 +131,11 @@ internal class YtDlpTask(
94
131
  onEvent(cancelledPayload())
95
132
  }
96
133
 
134
+ fun emitPaused() {
135
+ setStatus(YtDlpStatus.PAUSED)
136
+ onEvent(statePayload())
137
+ }
138
+
97
139
  fun emitError(code: String, message: String) {
98
140
  errorCode = code
99
141
  errorMessage = message
@@ -111,7 +153,7 @@ internal class YtDlpTask(
111
153
 
112
154
  private fun phaseOf(): String = when (status) {
113
155
  YtDlpStatus.QUEUED, YtDlpStatus.EXTRACTING -> "extracting"
114
- YtDlpStatus.DOWNLOADING -> "downloading"
156
+ YtDlpStatus.DOWNLOADING, YtDlpStatus.PAUSED -> "downloading"
115
157
  YtDlpStatus.PROCESSING, YtDlpStatus.COMPLETED -> "processing"
116
158
  YtDlpStatus.CANCELLED, YtDlpStatus.FAILED -> "downloading"
117
159
  }
@@ -29,6 +29,8 @@ export declare class ExpoYtDlpNativeModule extends NativeModule<ExpoYtDlpModuleE
29
29
  extractInfo(url: string, options: Record<string, unknown>): Promise<string>;
30
30
  startDownload(options: Record<string, unknown>): Promise<DownloadTaskInfo>;
31
31
  cancelDownload(taskId: string): Promise<boolean>;
32
+ pauseDownload(taskId: string): Promise<boolean>;
33
+ resumeDownload(taskId: string): Promise<boolean>;
32
34
  getDownloadStatus(taskId: string): Promise<DownloadStatusInfo | null>;
33
35
  }
34
36
  export declare const NativeExpoYtDlp: ExpoYtDlpNativeModule | null;
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoYtDlpModule.d.ts","sourceRoot":"","sources":["../src/ExpoYtDlpModule.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAA+B,MAAM,MAAM,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,YAAY,CAAC,qBAAqB,CAAC;IACpF,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAC7B,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3E,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAC1E,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAChD,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CACtE;AAED,eAAO,MAAM,eAAe,EAAE,qBAAqB,GAAG,IACW,CAAC"}
1
+ {"version":3,"file":"ExpoYtDlpModule.d.ts","sourceRoot":"","sources":["../src/ExpoYtDlpModule.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAA+B,MAAM,MAAM,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,YAAY,CAAC,qBAAqB,CAAC;IACpF,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAC7B,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3E,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAC1E,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAChD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAC/C,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAChD,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CACtE;AAED,eAAO,MAAM,eAAe,EAAE,qBAAqB,GAAG,IACW,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoYtDlpModule.js","sourceRoot":"","sources":["../src/ExpoYtDlpModule.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAgB,2BAA2B,EAAE,MAAM,MAAM,CAAC;AAgCjE,MAAM,CAAC,MAAM,eAAe,GAC1B,2BAA2B,CAAwB,WAAW,CAAC,CAAC","sourcesContent":["/**\n * Thin typed binding to the native `ExpoYtDlp` module.\n *\n * On unsupported platforms (web/iOS) the native module is absent; we detect\n * this here and surface it at call time as `UNSUPPORTED_PLATFORM`, so a plain\n * import never crashes.\n */\nimport { NativeModule, requireOptionalNativeModule } from 'expo';\n\nimport type { DownloadEvent, DownloadStatus } from './types';\n\nexport interface DownloadTaskInfo {\n taskId: string;\n directory: string;\n}\n\nexport interface DownloadStatusInfo {\n taskId: string;\n status: DownloadStatus;\n percent?: number;\n downloadedBytes?: number;\n totalBytes?: number;\n speedBytesPerSecond?: number;\n etaSeconds?: number;\n filename?: string;\n}\n\nexport type ExpoYtDlpModuleEvents = {\n downloadEvent: (event: DownloadEvent) => void;\n};\n\nexport declare class ExpoYtDlpNativeModule extends NativeModule<ExpoYtDlpModuleEvents> {\n getVersion(): Promise<string>;\n extractInfo(url: string, options: Record<string, unknown>): Promise<string>;\n startDownload(options: Record<string, unknown>): Promise<DownloadTaskInfo>;\n cancelDownload(taskId: string): Promise<boolean>;\n getDownloadStatus(taskId: string): Promise<DownloadStatusInfo | null>;\n}\n\nexport const NativeExpoYtDlp: ExpoYtDlpNativeModule | null =\n requireOptionalNativeModule<ExpoYtDlpNativeModule>('ExpoYtDlp');\n"]}
1
+ {"version":3,"file":"ExpoYtDlpModule.js","sourceRoot":"","sources":["../src/ExpoYtDlpModule.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAgB,2BAA2B,EAAE,MAAM,MAAM,CAAC;AAkCjE,MAAM,CAAC,MAAM,eAAe,GAC1B,2BAA2B,CAAwB,WAAW,CAAC,CAAC","sourcesContent":["/**\n * Thin typed binding to the native `ExpoYtDlp` module.\n *\n * On unsupported platforms (web/iOS) the native module is absent; we detect\n * this here and surface it at call time as `UNSUPPORTED_PLATFORM`, so a plain\n * import never crashes.\n */\nimport { NativeModule, requireOptionalNativeModule } from 'expo';\n\nimport type { DownloadEvent, DownloadStatus } from './types';\n\nexport interface DownloadTaskInfo {\n taskId: string;\n directory: string;\n}\n\nexport interface DownloadStatusInfo {\n taskId: string;\n status: DownloadStatus;\n percent?: number;\n downloadedBytes?: number;\n totalBytes?: number;\n speedBytesPerSecond?: number;\n etaSeconds?: number;\n filename?: string;\n}\n\nexport type ExpoYtDlpModuleEvents = {\n downloadEvent: (event: DownloadEvent) => void;\n};\n\nexport declare class ExpoYtDlpNativeModule extends NativeModule<ExpoYtDlpModuleEvents> {\n getVersion(): Promise<string>;\n extractInfo(url: string, options: Record<string, unknown>): Promise<string>;\n startDownload(options: Record<string, unknown>): Promise<DownloadTaskInfo>;\n cancelDownload(taskId: string): Promise<boolean>;\n pauseDownload(taskId: string): Promise<boolean>;\n resumeDownload(taskId: string): Promise<boolean>;\n getDownloadStatus(taskId: string): Promise<DownloadStatusInfo | null>;\n}\n\nexport const NativeExpoYtDlp: ExpoYtDlpNativeModule | null =\n requireOptionalNativeModule<ExpoYtDlpNativeModule>('ExpoYtDlp');\n"]}
package/build/YtDlp.d.ts CHANGED
@@ -20,4 +20,14 @@ export declare function getFormats(url: string, options?: ExtractOptions): Promi
20
20
  export declare function download(options: DownloadOptions): Promise<DownloadTask>;
21
21
  /** Cancel a download by task id, e.g. after app re-creation (AGENTS.md §22). */
22
22
  export declare function cancel(taskId: string): Promise<boolean>;
23
+ /**
24
+ * Pause an in-flight download by task id. Returns `false` if the task is
25
+ * unknown, already paused, or already finished.
26
+ */
27
+ export declare function pause(taskId: string): Promise<boolean>;
28
+ /**
29
+ * Resume a paused download by task id. Returns `false` if the task is unknown
30
+ * or not paused. yt-dlp continues from the partial `.part` file by default.
31
+ */
32
+ export declare function resume(taskId: string): Promise<boolean>;
23
33
  //# sourceMappingURL=YtDlp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"YtDlp.d.ts","sourceRoot":"","sources":["../src/YtDlp.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,eAAe,EACf,YAAY,EACZ,cAAc,EACd,MAAM,EACN,SAAS,EACT,YAAY,EACb,MAAM,SAAS,CAAC;AAejB;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAQxD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAS3F;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGzF;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAS9E;AAED,gFAAgF;AAChF,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D"}
1
+ {"version":3,"file":"YtDlp.d.ts","sourceRoot":"","sources":["../src/YtDlp.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,cAAc,EACd,MAAM,EACN,SAAS,EACT,YAAY,EACb,MAAM,SAAS,CAAC;AAejB;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAQxD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAS3F;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGzF;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAS9E;AAED,gFAAgF;AAChF,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D;AAED;;;GAGG;AACH,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO5D;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D"}
package/build/YtDlp.js CHANGED
@@ -3,6 +3,7 @@ import { LIBRARY_VERSION, SUPPORTED_PLATFORM_MESSAGE } from './constants';
3
3
  import { YtDlpDownloadTask } from './downloadTask';
4
4
  import { normalizeError, normalizeExtractionError, YtDlpError } from './errors';
5
5
  import { mapVideoInfo } from './mappers';
6
+ import { serializeDownloadOptions, serializeExtractOptions } from './serializers';
6
7
  function requireNative() {
7
8
  if (!NativeExpoYtDlp) {
8
9
  throw new YtDlpError('UNSUPPORTED_PLATFORM', SUPPORTED_PLATFORM_MESSAGE);
@@ -75,86 +76,30 @@ export async function cancel(taskId) {
75
76
  throw normalizeError(cause);
76
77
  }
77
78
  }
78
- function serializeExtractOptions(options) {
79
- if (!options)
80
- return {};
81
- const out = {};
82
- if (options.cookies)
83
- out.cookies = serializeCookies(options.cookies);
84
- if (options.proxy)
85
- out.proxy = options.proxy;
86
- if (options.userAgent || options.headers) {
87
- const headers = { ...(options.headers ?? {}) };
88
- if (options.userAgent)
89
- headers['User-Agent'] = options.userAgent;
90
- out.headers = headers;
91
- }
92
- return out;
93
- }
94
- function serializeDownloadOptions(options) {
95
- const out = { url: options.url };
96
- if (options.format)
97
- out.format = options.format;
98
- if (options.output) {
99
- const output = {};
100
- if (options.output.directory)
101
- output.directory = options.output.directory;
102
- if (options.output.filename)
103
- output.filename = options.output.filename;
104
- if (Object.keys(output).length > 0)
105
- out.output = output;
106
- }
107
- if (options.merge != null)
108
- out.merge = options.merge;
109
- if (options.cookies)
110
- out.cookies = serializeCookies(options.cookies);
111
- if (options.userAgent || options.headers) {
112
- const headers = { ...(options.headers ?? {}) };
113
- if (options.userAgent)
114
- headers['User-Agent'] = options.userAgent;
115
- out.headers = headers;
116
- }
117
- if (options.referer)
118
- out.referer = options.referer;
119
- if (options.proxy)
120
- out.proxy = options.proxy;
121
- if (options.playlist) {
122
- const playlist = {};
123
- if (options.playlist.enabled != null)
124
- playlist.enabled = options.playlist.enabled;
125
- if (options.playlist.start != null)
126
- playlist.start = options.playlist.start;
127
- if (options.playlist.end != null)
128
- playlist.end = options.playlist.end;
129
- if (Object.keys(playlist).length > 0)
130
- out.playlist = playlist;
131
- }
132
- if (options.network) {
133
- const network = {};
134
- if (options.network.timeout != null)
135
- network.timeout = options.network.timeout;
136
- if (options.network.retries != null)
137
- network.retries = options.network.retries;
138
- if (Object.keys(network).length > 0)
139
- out.network = network;
79
+ /**
80
+ * Pause an in-flight download by task id. Returns `false` if the task is
81
+ * unknown, already paused, or already finished.
82
+ */
83
+ export async function pause(taskId) {
84
+ try {
85
+ const native = requireNative();
86
+ return await native.pauseDownload(taskId);
140
87
  }
141
- if (options.subtitles) {
142
- const subtitles = {};
143
- if (options.subtitles.enabled != null)
144
- subtitles.enabled = options.subtitles.enabled;
145
- if (options.subtitles.languages?.length)
146
- subtitles.languages = options.subtitles.languages;
147
- if (options.subtitles.autoGenerated != null)
148
- subtitles.autoGenerated = options.subtitles.autoGenerated;
149
- if (Object.keys(subtitles).length > 0)
150
- out.subtitles = subtitles;
88
+ catch (cause) {
89
+ throw normalizeError(cause);
151
90
  }
152
- return out;
153
91
  }
154
- function serializeCookies(cookies) {
155
- if (cookies.source === 'file' && cookies.path) {
156
- return { path: cookies.path };
92
+ /**
93
+ * Resume a paused download by task id. Returns `false` if the task is unknown
94
+ * or not paused. yt-dlp continues from the partial `.part` file by default.
95
+ */
96
+ export async function resume(taskId) {
97
+ try {
98
+ const native = requireNative();
99
+ return await native.resumeDownload(taskId);
100
+ }
101
+ catch (cause) {
102
+ throw normalizeError(cause);
157
103
  }
158
- throw new YtDlpError('INVALID_URL', 'Cookies must reference a cookies file path.');
159
104
  }
160
105
  //# sourceMappingURL=YtDlp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"YtDlp.js","sourceRoot":"","sources":["../src/YtDlp.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeExpoYtDlp, type ExpoYtDlpNativeModule } from './ExpoYtDlpModule';\nimport { LIBRARY_VERSION, SUPPORTED_PLATFORM_MESSAGE } from './constants';\nimport { YtDlpDownloadTask } from './downloadTask';\nimport { normalizeError, normalizeExtractionError, YtDlpError } from './errors';\nimport { mapVideoInfo } from './mappers';\nimport type {\n CookieOptions,\n DownloadOptions,\n DownloadTask,\n ExtractOptions,\n Format,\n VideoInfo,\n YtDlpVersion,\n} from './types';\n\nfunction requireNative(): ExpoYtDlpNativeModule {\n if (!NativeExpoYtDlp) {\n throw new YtDlpError('UNSUPPORTED_PLATFORM', SUPPORTED_PLATFORM_MESSAGE);\n }\n return NativeExpoYtDlp;\n}\n\nfunction validateUrl(url: string | undefined): void {\n if (!url || url.trim().length === 0) {\n throw new YtDlpError('INVALID_URL', 'URL is required.');\n }\n}\n\n/**\n * Read the yt-dlp version embedded in the native runtime plus this package's\n * version. The two are independent (see AGENTS.md §35).\n */\nexport async function getVersion(): Promise<YtDlpVersion> {\n try {\n const native = requireNative();\n const ytDlp = await native.getVersion();\n return { ytDlp, library: LIBRARY_VERSION };\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n\n/**\n * Extract normalized media information without downloading anything.\n */\nexport async function extractInfo(url: string, options?: ExtractOptions): Promise<VideoInfo> {\n validateUrl(url);\n try {\n const native = requireNative();\n const json = await native.extractInfo(url, serializeExtractOptions(options));\n return mapVideoInfo(JSON.parse(json));\n } catch (cause) {\n throw normalizeExtractionError(cause);\n }\n}\n\n/**\n * List usable download formats. Internally reuses the same extraction as\n * `extractInfo` to avoid redundant work (see AGENTS.md §34).\n */\nexport async function getFormats(url: string, options?: ExtractOptions): Promise<Format[]> {\n const info = await extractInfo(url, options);\n return info.formats;\n}\n\n/**\n * Start a download. Resolves with a [DownloadTask] immediately; progress and\n * the final result arrive through the task's listeners (AGENTS.md §12).\n */\nexport async function download(options: DownloadOptions): Promise<DownloadTask> {\n validateUrl(options.url);\n try {\n const native = requireNative();\n const info = await native.startDownload(serializeDownloadOptions(options));\n return new YtDlpDownloadTask(native, info.taskId);\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n\n/** Cancel a download by task id, e.g. after app re-creation (AGENTS.md §22). */\nexport async function cancel(taskId: string): Promise<boolean> {\n try {\n const native = requireNative();\n return await native.cancelDownload(taskId);\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n\nfunction serializeExtractOptions(options: ExtractOptions | undefined): Record<string, unknown> {\n if (!options) return {};\n const out: Record<string, unknown> = {};\n if (options.cookies) out.cookies = serializeCookies(options.cookies);\n if (options.proxy) out.proxy = options.proxy;\n if (options.userAgent || options.headers) {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.userAgent) headers['User-Agent'] = options.userAgent;\n out.headers = headers;\n }\n return out;\n}\n\nfunction serializeDownloadOptions(options: DownloadOptions): Record<string, unknown> {\n const out: Record<string, unknown> = { url: options.url };\n if (options.format) out.format = options.format;\n if (options.output) {\n const output: Record<string, unknown> = {};\n if (options.output.directory) output.directory = options.output.directory;\n if (options.output.filename) output.filename = options.output.filename;\n if (Object.keys(output).length > 0) out.output = output;\n }\n if (options.merge != null) out.merge = options.merge;\n if (options.cookies) out.cookies = serializeCookies(options.cookies);\n if (options.userAgent || options.headers) {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.userAgent) headers['User-Agent'] = options.userAgent;\n out.headers = headers;\n }\n if (options.referer) out.referer = options.referer;\n if (options.proxy) out.proxy = options.proxy;\n if (options.playlist) {\n const playlist: Record<string, unknown> = {};\n if (options.playlist.enabled != null) playlist.enabled = options.playlist.enabled;\n if (options.playlist.start != null) playlist.start = options.playlist.start;\n if (options.playlist.end != null) playlist.end = options.playlist.end;\n if (Object.keys(playlist).length > 0) out.playlist = playlist;\n }\n if (options.network) {\n const network: Record<string, unknown> = {};\n if (options.network.timeout != null) network.timeout = options.network.timeout;\n if (options.network.retries != null) network.retries = options.network.retries;\n if (Object.keys(network).length > 0) out.network = network;\n }\n if (options.subtitles) {\n const subtitles: Record<string, unknown> = {};\n if (options.subtitles.enabled != null) subtitles.enabled = options.subtitles.enabled;\n if (options.subtitles.languages?.length) subtitles.languages = options.subtitles.languages;\n if (options.subtitles.autoGenerated != null)\n subtitles.autoGenerated = options.subtitles.autoGenerated;\n if (Object.keys(subtitles).length > 0) out.subtitles = subtitles;\n }\n return out;\n}\n\nfunction serializeCookies(cookies: CookieOptions): Record<string, unknown> {\n if (cookies.source === 'file' && cookies.path) {\n return { path: cookies.path };\n }\n throw new YtDlpError('INVALID_URL', 'Cookies must reference a cookies file path.');\n}\n"]}
1
+ {"version":3,"file":"YtDlp.js","sourceRoot":"","sources":["../src/YtDlp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA8B,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAUlF,SAAS,aAAa;IACpB,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,0BAA0B,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,SAAS,WAAW,CAAC,GAAuB;IAC1C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,UAAU,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,OAAwB;IACrE,WAAW,CAAC,GAAG,CAAC,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7E,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,OAAwB;IACpE,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,OAAO,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAwB;IACrD,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3E,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,MAAc;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,OAAO,MAAM,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,MAAc;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,OAAO,MAAM,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,MAAc;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,OAAO,MAAM,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC","sourcesContent":["import { NativeExpoYtDlp, type ExpoYtDlpNativeModule } from './ExpoYtDlpModule';\nimport { LIBRARY_VERSION, SUPPORTED_PLATFORM_MESSAGE } from './constants';\nimport { YtDlpDownloadTask } from './downloadTask';\nimport { normalizeError, normalizeExtractionError, YtDlpError } from './errors';\nimport { mapVideoInfo } from './mappers';\nimport { serializeDownloadOptions, serializeExtractOptions } from './serializers';\nimport type {\n DownloadOptions,\n DownloadTask,\n ExtractOptions,\n Format,\n VideoInfo,\n YtDlpVersion,\n} from './types';\n\nfunction requireNative(): ExpoYtDlpNativeModule {\n if (!NativeExpoYtDlp) {\n throw new YtDlpError('UNSUPPORTED_PLATFORM', SUPPORTED_PLATFORM_MESSAGE);\n }\n return NativeExpoYtDlp;\n}\n\nfunction validateUrl(url: string | undefined): void {\n if (!url || url.trim().length === 0) {\n throw new YtDlpError('INVALID_URL', 'URL is required.');\n }\n}\n\n/**\n * Read the yt-dlp version embedded in the native runtime plus this package's\n * version. The two are independent (see AGENTS.md §35).\n */\nexport async function getVersion(): Promise<YtDlpVersion> {\n try {\n const native = requireNative();\n const ytDlp = await native.getVersion();\n return { ytDlp, library: LIBRARY_VERSION };\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n\n/**\n * Extract normalized media information without downloading anything.\n */\nexport async function extractInfo(url: string, options?: ExtractOptions): Promise<VideoInfo> {\n validateUrl(url);\n try {\n const native = requireNative();\n const json = await native.extractInfo(url, serializeExtractOptions(options));\n return mapVideoInfo(JSON.parse(json));\n } catch (cause) {\n throw normalizeExtractionError(cause);\n }\n}\n\n/**\n * List usable download formats. Internally reuses the same extraction as\n * `extractInfo` to avoid redundant work (see AGENTS.md §34).\n */\nexport async function getFormats(url: string, options?: ExtractOptions): Promise<Format[]> {\n const info = await extractInfo(url, options);\n return info.formats;\n}\n\n/**\n * Start a download. Resolves with a [DownloadTask] immediately; progress and\n * the final result arrive through the task's listeners (AGENTS.md §12).\n */\nexport async function download(options: DownloadOptions): Promise<DownloadTask> {\n validateUrl(options.url);\n try {\n const native = requireNative();\n const info = await native.startDownload(serializeDownloadOptions(options));\n return new YtDlpDownloadTask(native, info.taskId);\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n\n/** Cancel a download by task id, e.g. after app re-creation (AGENTS.md §22). */\nexport async function cancel(taskId: string): Promise<boolean> {\n try {\n const native = requireNative();\n return await native.cancelDownload(taskId);\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n\n/**\n * Pause an in-flight download by task id. Returns `false` if the task is\n * unknown, already paused, or already finished.\n */\nexport async function pause(taskId: string): Promise<boolean> {\n try {\n const native = requireNative();\n return await native.pauseDownload(taskId);\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n\n/**\n * Resume a paused download by task id. Returns `false` if the task is unknown\n * or not paused. yt-dlp continues from the partial `.part` file by default.\n */\nexport async function resume(taskId: string): Promise<boolean> {\n try {\n const native = requireNative();\n return await native.resumeDownload(taskId);\n } catch (cause) {\n throw normalizeError(cause);\n }\n}\n"]}
@@ -1,7 +1,4 @@
1
- /**
2
- * Package-level constants.
3
- */
4
- export declare const LIBRARY_VERSION = "0.1.0";
1
+ export declare const LIBRARY_VERSION: string;
5
2
  export declare const SUPPORTED_PLATFORM = "android";
6
3
  export declare const SUPPORTED_PLATFORM_MESSAGE = "expo-ytdlp-native is currently supported on android only.";
7
4
  /** yt-dlp output template used when the caller does not provide a filename. */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C,eAAO,MAAM,0BAA0B,8DAAiF,CAAC;AAEzH,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,sBAAsB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,QAAc,CAAC;AAE3C,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C,eAAO,MAAM,0BAA0B,8DAAiF,CAAC;AAEzH,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,sBAAsB,CAAC"}
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Package-level constants.
3
3
  */
4
- export const LIBRARY_VERSION = '0.1.0';
4
+ import pkg from '../package.json';
5
+ export const LIBRARY_VERSION = pkg.version;
5
6
  export const SUPPORTED_PLATFORM = 'android';
6
7
  export const SUPPORTED_PLATFORM_MESSAGE = `${'expo-ytdlp-native'} is currently supported on ${SUPPORTED_PLATFORM} only.`;
7
8
  /** yt-dlp output template used when the caller does not provide a filename. */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAE5C,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,mBAAmB,8BAA8B,kBAAkB,QAAQ,CAAC;AAEzH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,yBAAyB,GAAG,mBAAmB,CAAC","sourcesContent":["/**\n * Package-level constants.\n */\nexport const LIBRARY_VERSION = '0.1.0';\n\nexport const SUPPORTED_PLATFORM = 'android';\n\nexport const SUPPORTED_PLATFORM_MESSAGE = `${'expo-ytdlp-native'} is currently supported on ${SUPPORTED_PLATFORM} only.`;\n\n/** yt-dlp output template used when the caller does not provide a filename. */\nexport const DEFAULT_FILENAME_TEMPLATE = '%(title)s.%(ext)s';\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,GAAG,MAAM,iBAAiB,CAAC;AAElC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC;AAE3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAE5C,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,mBAAmB,8BAA8B,kBAAkB,QAAQ,CAAC;AAEzH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,yBAAyB,GAAG,mBAAmB,CAAC","sourcesContent":["/**\n * Package-level constants.\n */\nimport pkg from '../package.json';\n\nexport const LIBRARY_VERSION = pkg.version;\n\nexport const SUPPORTED_PLATFORM = 'android';\n\nexport const SUPPORTED_PLATFORM_MESSAGE = `${'expo-ytdlp-native'} is currently supported on ${SUPPORTED_PLATFORM} only.`;\n\n/** yt-dlp output template used when the caller does not provide a filename. */\nexport const DEFAULT_FILENAME_TEMPLATE = '%(title)s.%(ext)s';\n"]}
@@ -18,6 +18,8 @@ export declare class YtDlpDownloadTask implements DownloadTask {
18
18
  private subscriptions;
19
19
  constructor(native: ExpoYtDlpNativeModule, id: string);
20
20
  cancel(): Promise<void>;
21
+ pause(): Promise<boolean>;
22
+ resume(): Promise<boolean>;
21
23
  getStatus(): Promise<DownloadStatus>;
22
24
  getProgress(): Promise<DownloadProgress | null>;
23
25
  addListener(event: 'progress', listener: Listener<DownloadProgress>): Subscription;
@@ -1 +1 @@
1
- {"version":3,"file":"downloadTask.d.ts","sourceRoot":"","sources":["../src/downloadTask.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAsB,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAStC,qBAAa,iBAAkB,YAAW,YAAY;IACpD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAKxB;IACF,OAAO,CAAC,aAAa,CAAsB;gBAE/B,MAAM,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM;IAgC/C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IAOpC,WAAW,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAMrD,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAClF,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GAAG,YAAY;IACjF,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,YAAY;IACjF,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAyBzE,OAAO,CAAC,QAAQ;CAIjB"}
1
+ {"version":3,"file":"downloadTask.d.ts","sourceRoot":"","sources":["../src/downloadTask.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAsB,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAStC,qBAAa,iBAAkB,YAAW,YAAY;IACpD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAKxB;IACF,OAAO,CAAC,aAAa,CAAsB;gBAE/B,MAAM,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM;IAgC/C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IAOpC,WAAW,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAMrD,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAClF,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GAAG,YAAY;IACjF,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,YAAY;IACjF,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAyBzE,OAAO,CAAC,QAAQ;CAIjB"}
@@ -45,6 +45,12 @@ export class YtDlpDownloadTask {
45
45
  async cancel() {
46
46
  await this.native.cancelDownload(this.id);
47
47
  }
48
+ async pause() {
49
+ return this.native.pauseDownload(this.id);
50
+ }
51
+ async resume() {
52
+ return this.native.resumeDownload(this.id);
53
+ }
48
54
  async getStatus() {
49
55
  if (this.finalized)
50
56
  return this.currentStatus;
@@ -95,6 +101,7 @@ function mapStatusInfo(taskId, fallbackStatus, info) {
95
101
  function phaseOf(status) {
96
102
  switch (status) {
97
103
  case 'downloading':
104
+ case 'paused':
98
105
  return 'downloading';
99
106
  case 'completed':
100
107
  case 'processing':
@@ -1 +1 @@
1
- {"version":3,"file":"downloadTask.js","sourceRoot":"","sources":["../src/downloadTask.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * JS-side `DownloadTask` implementation.\n *\n * Keeps this module dependency-light: all per-task state lives in the native\n * task registry; the JS object only relays events and forwards commands\n * (AGENTS.md §17, §47).\n */\nimport type { DownloadStatusInfo, ExpoYtDlpNativeModule } from './ExpoYtDlpModule';\nimport { YtDlpError } from './errors';\nimport { attachTaskListeners } from './events';\nimport type {\n DownloadProgress,\n DownloadResult,\n DownloadStateEvent,\n DownloadStatus,\n DownloadTask,\n Subscription,\n} from './types';\n\ntype Listener<T> = (value: T) => void;\n\ninterface TaskListenerSets {\n progress: Set<Listener<DownloadProgress>>;\n state: Set<Listener<DownloadStateEvent>>;\n completed: Set<Listener<DownloadResult>>;\n error: Set<Listener<YtDlpError>>;\n}\n\nexport class YtDlpDownloadTask implements DownloadTask {\n readonly id: string;\n\n private readonly native: ExpoYtDlpNativeModule;\n private currentStatus: DownloadStatus = 'queued';\n private finalized = false;\n private readonly listeners: TaskListenerSets = {\n progress: new Set(),\n state: new Set(),\n completed: new Set(),\n error: new Set(),\n };\n private subscriptions: Subscription[] = [];\n\n constructor(native: ExpoYtDlpNativeModule, id: string) {\n this.native = native;\n this.id = id;\n this.subscriptions = attachTaskListeners(id, {\n progress: (progress) => {\n this.currentStatus = progress.status;\n this.listeners.progress.forEach((listener) => listener(progress));\n },\n state: (state) => {\n this.currentStatus = state.status;\n this.listeners.state.forEach((listener) => listener(state));\n },\n completed: (result) => {\n this.finalized = true;\n this.currentStatus = 'completed';\n this.teardown();\n this.listeners.completed.forEach((listener) => listener(result));\n },\n cancelled: () => {\n this.finalized = true;\n this.currentStatus = 'cancelled';\n this.teardown();\n },\n error: (error) => {\n this.finalized = true;\n this.currentStatus = 'failed';\n this.teardown();\n this.listeners.error.forEach((listener) => listener(error));\n },\n });\n }\n\n async cancel(): Promise<void> {\n await this.native.cancelDownload(this.id);\n }\n\n async getStatus(): Promise<DownloadStatus> {\n if (this.finalized) return this.currentStatus;\n const info = await this.native.getDownloadStatus(this.id);\n if (info?.status) this.currentStatus = info.status;\n return this.currentStatus;\n }\n\n async getProgress(): Promise<DownloadProgress | null> {\n const info = await this.native.getDownloadStatus(this.id);\n if (!info) return null;\n return mapStatusInfo(this.id, this.currentStatus, info);\n }\n\n addListener(event: 'progress', listener: Listener<DownloadProgress>): Subscription;\n addListener(event: 'state', listener: Listener<DownloadStateEvent>): Subscription;\n addListener(event: 'completed', listener: Listener<DownloadResult>): Subscription;\n addListener(event: 'error', listener: Listener<YtDlpError>): Subscription;\n addListener(\n event: 'progress' | 'state' | 'completed' | 'error',\n listener:\n | Listener<DownloadProgress>\n | Listener<DownloadStateEvent>\n | Listener<DownloadResult>\n | Listener<YtDlpError>\n ): Subscription {\n const set =\n event === 'progress'\n ? this.listeners.progress\n : event === 'state'\n ? this.listeners.state\n : event === 'completed'\n ? this.listeners.completed\n : this.listeners.error;\n set.add(listener as never);\n return {\n remove: () => {\n set.delete(listener as never);\n },\n };\n }\n\n private teardown() {\n this.subscriptions.forEach((subscription) => subscription.remove());\n this.subscriptions = [];\n }\n}\n\nfunction mapStatusInfo(\n taskId: string,\n fallbackStatus: DownloadStatus,\n info: DownloadStatusInfo\n): DownloadProgress {\n return {\n taskId,\n status: (info.status ?? fallbackStatus) as DownloadStatus,\n phase: phaseOf(info.status),\n percent: finiteOrUndefined(info.percent),\n downloadedBytes: finiteOrUndefined(info.downloadedBytes),\n totalBytes: finiteOrUndefined(info.totalBytes),\n speedBytesPerSecond: finiteOrUndefined(info.speedBytesPerSecond),\n etaSeconds: finiteOrUndefined(info.etaSeconds),\n filename: info.filename,\n };\n}\n\nfunction phaseOf(status: DownloadStatus): DownloadProgress['phase'] {\n switch (status) {\n case 'downloading':\n return 'downloading';\n case 'completed':\n case 'processing':\n return 'processing';\n default:\n return 'extracting';\n }\n}\n\nfunction finiteOrUndefined(value: number | undefined): number | undefined {\n if (value === undefined || value === null) return undefined;\n return Number.isFinite(value) ? value : undefined;\n}\n"]}
1
+ {"version":3,"file":"downloadTask.js","sourceRoot":"","sources":["../src/downloadTask.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * JS-side `DownloadTask` implementation.\n *\n * Keeps this module dependency-light: all per-task state lives in the native\n * task registry; the JS object only relays events and forwards commands\n * (AGENTS.md §17, §47).\n */\nimport type { DownloadStatusInfo, ExpoYtDlpNativeModule } from './ExpoYtDlpModule';\nimport { YtDlpError } from './errors';\nimport { attachTaskListeners } from './events';\nimport type {\n DownloadProgress,\n DownloadResult,\n DownloadStateEvent,\n DownloadStatus,\n DownloadTask,\n Subscription,\n} from './types';\n\ntype Listener<T> = (value: T) => void;\n\ninterface TaskListenerSets {\n progress: Set<Listener<DownloadProgress>>;\n state: Set<Listener<DownloadStateEvent>>;\n completed: Set<Listener<DownloadResult>>;\n error: Set<Listener<YtDlpError>>;\n}\n\nexport class YtDlpDownloadTask implements DownloadTask {\n readonly id: string;\n\n private readonly native: ExpoYtDlpNativeModule;\n private currentStatus: DownloadStatus = 'queued';\n private finalized = false;\n private readonly listeners: TaskListenerSets = {\n progress: new Set(),\n state: new Set(),\n completed: new Set(),\n error: new Set(),\n };\n private subscriptions: Subscription[] = [];\n\n constructor(native: ExpoYtDlpNativeModule, id: string) {\n this.native = native;\n this.id = id;\n this.subscriptions = attachTaskListeners(id, {\n progress: (progress) => {\n this.currentStatus = progress.status;\n this.listeners.progress.forEach((listener) => listener(progress));\n },\n state: (state) => {\n this.currentStatus = state.status;\n this.listeners.state.forEach((listener) => listener(state));\n },\n completed: (result) => {\n this.finalized = true;\n this.currentStatus = 'completed';\n this.teardown();\n this.listeners.completed.forEach((listener) => listener(result));\n },\n cancelled: () => {\n this.finalized = true;\n this.currentStatus = 'cancelled';\n this.teardown();\n },\n error: (error) => {\n this.finalized = true;\n this.currentStatus = 'failed';\n this.teardown();\n this.listeners.error.forEach((listener) => listener(error));\n },\n });\n }\n\n async cancel(): Promise<void> {\n await this.native.cancelDownload(this.id);\n }\n\n async pause(): Promise<boolean> {\n return this.native.pauseDownload(this.id);\n }\n\n async resume(): Promise<boolean> {\n return this.native.resumeDownload(this.id);\n }\n\n async getStatus(): Promise<DownloadStatus> {\n if (this.finalized) return this.currentStatus;\n const info = await this.native.getDownloadStatus(this.id);\n if (info?.status) this.currentStatus = info.status;\n return this.currentStatus;\n }\n\n async getProgress(): Promise<DownloadProgress | null> {\n const info = await this.native.getDownloadStatus(this.id);\n if (!info) return null;\n return mapStatusInfo(this.id, this.currentStatus, info);\n }\n\n addListener(event: 'progress', listener: Listener<DownloadProgress>): Subscription;\n addListener(event: 'state', listener: Listener<DownloadStateEvent>): Subscription;\n addListener(event: 'completed', listener: Listener<DownloadResult>): Subscription;\n addListener(event: 'error', listener: Listener<YtDlpError>): Subscription;\n addListener(\n event: 'progress' | 'state' | 'completed' | 'error',\n listener:\n | Listener<DownloadProgress>\n | Listener<DownloadStateEvent>\n | Listener<DownloadResult>\n | Listener<YtDlpError>\n ): Subscription {\n const set =\n event === 'progress'\n ? this.listeners.progress\n : event === 'state'\n ? this.listeners.state\n : event === 'completed'\n ? this.listeners.completed\n : this.listeners.error;\n set.add(listener as never);\n return {\n remove: () => {\n set.delete(listener as never);\n },\n };\n }\n\n private teardown() {\n this.subscriptions.forEach((subscription) => subscription.remove());\n this.subscriptions = [];\n }\n}\n\nfunction mapStatusInfo(\n taskId: string,\n fallbackStatus: DownloadStatus,\n info: DownloadStatusInfo\n): DownloadProgress {\n return {\n taskId,\n status: (info.status ?? fallbackStatus) as DownloadStatus,\n phase: phaseOf(info.status),\n percent: finiteOrUndefined(info.percent),\n downloadedBytes: finiteOrUndefined(info.downloadedBytes),\n totalBytes: finiteOrUndefined(info.totalBytes),\n speedBytesPerSecond: finiteOrUndefined(info.speedBytesPerSecond),\n etaSeconds: finiteOrUndefined(info.etaSeconds),\n filename: info.filename,\n };\n}\n\nfunction phaseOf(status: DownloadStatus): DownloadProgress['phase'] {\n switch (status) {\n case 'downloading':\n case 'paused':\n return 'downloading';\n case 'completed':\n case 'processing':\n return 'processing';\n default:\n return 'extracting';\n }\n}\n\nfunction finiteOrUndefined(value: number | undefined): number | undefined {\n if (value === undefined || value === null) return undefined;\n return Number.isFinite(value) ? value : undefined;\n}\n"]}
package/build/errors.js CHANGED
@@ -90,6 +90,9 @@ export function normalizeExtractionError(cause, fallbackMessage = 'Failed to ext
90
90
  if (/http error|connection|timed out|unreachable|name or service not known|failed to establish|reset by peer|couldn't connect|503|429/.test(message)) {
91
91
  return new YtDlpError('NETWORK_ERROR', base.message, { cause: base.cause });
92
92
  }
93
+ if (message.includes('age') || message.includes('mature') || message.includes('under 18')) {
94
+ return new YtDlpError('AGE_RESTRICTED', base.message, { cause: base.cause });
95
+ }
93
96
  if (message.includes('sign in to confirm') ||
94
97
  message.includes('log in') ||
95
98
  message.includes('sign up')) {
@@ -98,9 +101,6 @@ export function normalizeExtractionError(cause, fallbackMessage = 'Failed to ext
98
101
  if (message.includes('private') || message.includes('members-only')) {
99
102
  return new YtDlpError('PRIVATE_CONTENT', base.message, { cause: base.cause });
100
103
  }
101
- if (message.includes('age') || message.includes('mature') || message.includes('under 18')) {
102
- return new YtDlpError('AGE_RESTRICTED', base.message, { cause: base.cause });
103
- }
104
104
  if (message.includes('geographic') ||
105
105
  message.includes('geo-') ||
106
106
  message.includes('not available in your country')) {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { YtDlpErrorCode } from './types';\n\n/** Prefix used by the Kotlin layer to carry error codes across the bridge. */\nconst NATIVE_PREFIX = 'YTD_NATIVE|';\n\nexport class YtDlpError extends Error {\n readonly code: YtDlpErrorCode;\n readonly taskId?: string;\n readonly cause?: unknown;\n\n constructor(\n code: YtDlpErrorCode,\n message: string,\n options?: { taskId?: string; cause?: unknown }\n ) {\n super(message);\n this.name = 'YtDlpError';\n this.code = code;\n if (options?.taskId) this.taskId = options.taskId;\n if (options?.cause !== undefined) this.cause = options.cause;\n }\n}\n\n/**\n * Normalizes anything thrown by the native layer into a `YtDlpError`.\n * Unknown/missing codes map to `UNKNOWN`; raw stack traces are never surfaced.\n */\nexport function normalizeError(\n cause: unknown,\n fallbackMessage = 'Unknown yt-dlp error'\n): YtDlpError {\n if (cause instanceof YtDlpError) return cause;\n\n if (cause instanceof Error) {\n const parsed = parseNativeMessage(cause.message);\n if (parsed) {\n return new YtDlpError(parsed.code, parsed.message, { cause });\n }\n return new YtDlpError('UNKNOWN', cause.message || fallbackMessage, { cause });\n }\n\n if (typeof cause === 'string') {\n const parsed = parseNativeMessage(cause);\n if (parsed) return new YtDlpError(parsed.code, parsed.message);\n return new YtDlpError('UNKNOWN', cause || fallbackMessage);\n }\n\n return new YtDlpError('UNKNOWN', fallbackMessage, { cause });\n}\n\nfunction parseNativeMessage(message: string): { code: YtDlpErrorCode; message: string } | null {\n if (!message.startsWith(NATIVE_PREFIX)) return null;\n const rest = message.slice(NATIVE_PREFIX.length);\n const separator = rest.indexOf('|');\n if (separator === -1) return null;\n const rawCode = rest.slice(0, separator);\n const text = rest.slice(separator + 1);\n const code = toKnownCode(rawCode);\n return { code, message: text || rawCode };\n}\n\nfunction toKnownCode(rawCode: string): YtDlpErrorCode {\n const known: YtDlpErrorCode[] = [\n 'INVALID_URL',\n 'EXTRACTION_FAILED',\n 'DOWNLOAD_FAILED',\n 'CANCELLED',\n 'FORMAT_UNAVAILABLE',\n 'NETWORK_ERROR',\n 'AUTHENTICATION_REQUIRED',\n 'GEO_RESTRICTED',\n 'PRIVATE_CONTENT',\n 'AGE_RESTRICTED',\n 'PROCESSING_FAILED',\n 'STORAGE_ERROR',\n 'INIT_FAILED',\n 'UNSUPPORTED_PLATFORM',\n 'UNKNOWN',\n ];\n if ((known as readonly string[]).includes(rawCode)) return rawCode as YtDlpErrorCode;\n return 'UNKNOWN';\n}\n\n/**\n * Builds a `YtDlpError` from a code+message pair received from native events.\n * Unknown codes degrade to `UNKNOWN` (AGENTS.md §23).\n */\nexport function fromNativeCode(code: string, message: string): YtDlpError {\n return new YtDlpError(toKnownCode(code), message);\n}\n\n/**\n * Refines an extraction failure into a more specific code by matching the\n * yt-dlp error message. Kept conservative: no match falls back to the\n * normalized code.\n */\nexport function normalizeExtractionError(\n cause: unknown,\n fallbackMessage = 'Failed to extract media information'\n): YtDlpError {\n const base = normalizeError(cause, fallbackMessage);\n if (base.code !== 'EXTRACTION_FAILED' && base.code !== 'UNKNOWN') return base;\n\n const message = base.message.toLowerCase();\n if (\n /http error|connection|timed out|unreachable|name or service not known|failed to establish|reset by peer|couldn't connect|503|429/.test(\n message\n )\n ) {\n return new YtDlpError('NETWORK_ERROR', base.message, { cause: base.cause });\n }\n if (\n message.includes('sign in to confirm') ||\n message.includes('log in') ||\n message.includes('sign up')\n ) {\n return new YtDlpError('AUTHENTICATION_REQUIRED', base.message, { cause: base.cause });\n }\n if (message.includes('private') || message.includes('members-only')) {\n return new YtDlpError('PRIVATE_CONTENT', base.message, { cause: base.cause });\n }\n if (message.includes('age') || message.includes('mature') || message.includes('under 18')) {\n return new YtDlpError('AGE_RESTRICTED', base.message, { cause: base.cause });\n }\n if (\n message.includes('geographic') ||\n message.includes('geo-') ||\n message.includes('not available in your country')\n ) {\n return new YtDlpError('GEO_RESTRICTED', base.message, { cause: base.cause });\n }\n return base;\n}\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { YtDlpErrorCode } from './types';\n\n/** Prefix used by the Kotlin layer to carry error codes across the bridge. */\nconst NATIVE_PREFIX = 'YTD_NATIVE|';\n\nexport class YtDlpError extends Error {\n readonly code: YtDlpErrorCode;\n readonly taskId?: string;\n readonly cause?: unknown;\n\n constructor(\n code: YtDlpErrorCode,\n message: string,\n options?: { taskId?: string; cause?: unknown }\n ) {\n super(message);\n this.name = 'YtDlpError';\n this.code = code;\n if (options?.taskId) this.taskId = options.taskId;\n if (options?.cause !== undefined) this.cause = options.cause;\n }\n}\n\n/**\n * Normalizes anything thrown by the native layer into a `YtDlpError`.\n * Unknown/missing codes map to `UNKNOWN`; raw stack traces are never surfaced.\n */\nexport function normalizeError(\n cause: unknown,\n fallbackMessage = 'Unknown yt-dlp error'\n): YtDlpError {\n if (cause instanceof YtDlpError) return cause;\n\n if (cause instanceof Error) {\n const parsed = parseNativeMessage(cause.message);\n if (parsed) {\n return new YtDlpError(parsed.code, parsed.message, { cause });\n }\n return new YtDlpError('UNKNOWN', cause.message || fallbackMessage, { cause });\n }\n\n if (typeof cause === 'string') {\n const parsed = parseNativeMessage(cause);\n if (parsed) return new YtDlpError(parsed.code, parsed.message);\n return new YtDlpError('UNKNOWN', cause || fallbackMessage);\n }\n\n return new YtDlpError('UNKNOWN', fallbackMessage, { cause });\n}\n\nfunction parseNativeMessage(message: string): { code: YtDlpErrorCode; message: string } | null {\n if (!message.startsWith(NATIVE_PREFIX)) return null;\n const rest = message.slice(NATIVE_PREFIX.length);\n const separator = rest.indexOf('|');\n if (separator === -1) return null;\n const rawCode = rest.slice(0, separator);\n const text = rest.slice(separator + 1);\n const code = toKnownCode(rawCode);\n return { code, message: text || rawCode };\n}\n\nfunction toKnownCode(rawCode: string): YtDlpErrorCode {\n const known: YtDlpErrorCode[] = [\n 'INVALID_URL',\n 'EXTRACTION_FAILED',\n 'DOWNLOAD_FAILED',\n 'CANCELLED',\n 'FORMAT_UNAVAILABLE',\n 'NETWORK_ERROR',\n 'AUTHENTICATION_REQUIRED',\n 'GEO_RESTRICTED',\n 'PRIVATE_CONTENT',\n 'AGE_RESTRICTED',\n 'PROCESSING_FAILED',\n 'STORAGE_ERROR',\n 'INIT_FAILED',\n 'UNSUPPORTED_PLATFORM',\n 'UNKNOWN',\n ];\n if ((known as readonly string[]).includes(rawCode)) return rawCode as YtDlpErrorCode;\n return 'UNKNOWN';\n}\n\n/**\n * Builds a `YtDlpError` from a code+message pair received from native events.\n * Unknown codes degrade to `UNKNOWN` (AGENTS.md §23).\n */\nexport function fromNativeCode(code: string, message: string): YtDlpError {\n return new YtDlpError(toKnownCode(code), message);\n}\n\n/**\n * Refines an extraction failure into a more specific code by matching the\n * yt-dlp error message. Kept conservative: no match falls back to the\n * normalized code.\n */\nexport function normalizeExtractionError(\n cause: unknown,\n fallbackMessage = 'Failed to extract media information'\n): YtDlpError {\n const base = normalizeError(cause, fallbackMessage);\n if (base.code !== 'EXTRACTION_FAILED' && base.code !== 'UNKNOWN') return base;\n\n const message = base.message.toLowerCase();\n if (\n /http error|connection|timed out|unreachable|name or service not known|failed to establish|reset by peer|couldn't connect|503|429/.test(\n message\n )\n ) {\n return new YtDlpError('NETWORK_ERROR', base.message, { cause: base.cause });\n }\n if (message.includes('age') || message.includes('mature') || message.includes('under 18')) {\n return new YtDlpError('AGE_RESTRICTED', base.message, { cause: base.cause });\n }\n if (\n message.includes('sign in to confirm') ||\n message.includes('log in') ||\n message.includes('sign up')\n ) {\n return new YtDlpError('AUTHENTICATION_REQUIRED', base.message, { cause: base.cause });\n }\n if (message.includes('private') || message.includes('members-only')) {\n return new YtDlpError('PRIVATE_CONTENT', base.message, { cause: base.cause });\n }\n if (\n message.includes('geographic') ||\n message.includes('geo-') ||\n message.includes('not available in your country')\n ) {\n return new YtDlpError('GEO_RESTRICTED', base.message, { cause: base.cause });\n }\n return base;\n}\n"]}
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { cancel, download, extractInfo, getFormats, getVersion } from './YtDlp';
1
+ import { cancel, download, extractInfo, getFormats, getVersion, pause, resume } from './YtDlp';
2
2
  import { YtDlpError } from './errors';
3
3
  export type * from './types';
4
4
  /** Main SDK facade. */
@@ -8,6 +8,8 @@ export declare const YtDlp: {
8
8
  getFormats: typeof getFormats;
9
9
  download: typeof download;
10
10
  cancel: typeof cancel;
11
+ pause: typeof pause;
12
+ resume: typeof resume;
11
13
  };
12
14
  export { YtDlpError };
13
15
  export default YtDlp;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,mBAAmB,SAAS,CAAC;AAE7B,uBAAuB;AACvB,eAAO,MAAM,KAAK;;;;;;CAMjB,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,mBAAmB,SAAS,CAAC;AAE7B,uBAAuB;AACvB,eAAO,MAAM,KAAK;;;;;;;;CAQjB,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,eAAe,KAAK,CAAC"}
package/build/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { cancel, download, extractInfo, getFormats, getVersion } from './YtDlp';
1
+ import { cancel, download, extractInfo, getFormats, getVersion, pause, resume } from './YtDlp';
2
2
  import { YtDlpError } from './errors';
3
3
  /** Main SDK facade. */
4
4
  export const YtDlp = {
@@ -7,6 +7,8 @@ export const YtDlp = {
7
7
  getFormats,
8
8
  download,
9
9
  cancel,
10
+ pause,
11
+ resume,
10
12
  };
11
13
  export { YtDlpError };
12
14
  export default YtDlp;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAItC,uBAAuB;AACvB,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,UAAU;IACV,WAAW;IACX,UAAU;IACV,QAAQ;IACR,MAAM;CACP,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,eAAe,KAAK,CAAC","sourcesContent":["import { cancel, download, extractInfo, getFormats, getVersion } from './YtDlp';\nimport { YtDlpError } from './errors';\n\nexport type * from './types';\n\n/** Main SDK facade. */\nexport const YtDlp = {\n getVersion,\n extractInfo,\n getFormats,\n download,\n cancel,\n};\n\nexport { YtDlpError };\n\nexport default YtDlp;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAItC,uBAAuB;AACvB,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,UAAU;IACV,WAAW;IACX,UAAU;IACV,QAAQ;IACR,MAAM;IACN,KAAK;IACL,MAAM;CACP,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,eAAe,KAAK,CAAC","sourcesContent":["import { cancel, download, extractInfo, getFormats, getVersion, pause, resume } from './YtDlp';\nimport { YtDlpError } from './errors';\n\nexport type * from './types';\n\n/** Main SDK facade. */\nexport const YtDlp = {\n getVersion,\n extractInfo,\n getFormats,\n download,\n cancel,\n pause,\n resume,\n};\n\nexport { YtDlpError };\n\nexport default YtDlp;\n"]}
package/build/mappers.js CHANGED
@@ -71,9 +71,9 @@ export function mapFormat(raw) {
71
71
  * `DownloadProgress`, replacing any non-finite numbers with `undefined`.
72
72
  */
73
73
  export function mapDownloadProgress(raw, taskId) {
74
- const progress = asRecord(raw);
75
- if (!progress)
74
+ if (typeof raw !== 'object' || raw === null)
76
75
  return null;
76
+ const progress = raw;
77
77
  const percent = numberOf(progress.percent);
78
78
  const phaseRaw = stringOf(progress.phase);
79
79
  return {
@@ -95,6 +95,7 @@ function statusOf(value) {
95
95
  case 'extracting':
96
96
  case 'downloading':
97
97
  case 'processing':
98
+ case 'paused':
98
99
  case 'completed':
99
100
  case 'cancelled':
100
101
  case 'failed':
@@ -1 +1 @@
1
- {"version":3,"file":"mappers.js","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mapping from the raw JSON produced by yt-dlp into the stable public types.\n *\n * Everything is defensive: unknown fields become `undefined`, never fake\n * values (see AGENTS.md §11, §69, §70).\n */\nimport type { DownloadProgress, Format, Thumbnail, VideoInfo } from './types';\n\ntype RawRecord = Record<string, unknown>;\n\nconst NONE_CODEC = 'none';\n\nexport function mapVideoInfo(raw: unknown): VideoInfo {\n const info = asRecord(raw);\n\n const formats = Array.isArray(info.formats) ? info.formats.map(mapFormat) : [];\n\n const liveStatus = stringOf(info.live_status);\n const thumbnails = normalizeThumbnails(info.thumbnails, stringOf(info.thumbnail));\n\n return {\n id: stringOf(info.id),\n title: stringOf(info.title),\n description: stringOf(info.description),\n uploader: stringOf(info.uploader),\n uploaderId: stringOf(info.uploader_id),\n uploaderUrl: stringOf(info.uploader_url),\n channel: stringOf(info.channel),\n channelId: stringOf(info.channel_id),\n channelUrl: stringOf(info.channel_url),\n webpageUrl: stringOf(info.webpage_url),\n originalUrl: stringOf(info.original_url),\n thumbnail: firstThumbnailUrl(thumbnails) ?? stringOf(info.thumbnail),\n thumbnails,\n duration: numberOf(info.duration),\n durationString: stringOf(info.duration_string),\n uploadDate: stringOf(info.upload_date),\n timestamp: numberOf(info.timestamp),\n viewCount: numberOf(info.view_count),\n likeCount: numberOf(info.like_count),\n commentCount: numberOf(info.comment_count),\n ageLimit: numberOf(info.age_limit),\n isLive: liveStatus === 'is_live',\n wasLive: liveStatus === 'was_live',\n extractor: stringOf(info.extractor),\n extractorKey: stringOf(info.extractor_key),\n webpageUrlDomain: stringOf(info.webpage_url_domain),\n formats,\n };\n}\n\nexport function mapFormat(raw: unknown): Format {\n const format = asRecord(raw);\n const vcodec = stringOf(format.vcodec);\n const acodec = stringOf(format.acodec);\n const hasVideo = vcodec !== undefined && vcodec.toLowerCase() !== NONE_CODEC;\n const hasAudio = acodec !== undefined && acodec.toLowerCase() !== NONE_CODEC;\n\n return {\n id: stringOf(format.format_id) ?? stringOf(format.id) ?? '',\n url: stringOf(format.url),\n ext: stringOf(format.ext),\n protocol: stringOf(format.protocol),\n format: stringOf(format.format),\n formatNote: stringOf(format.format_note),\n width: numberOf(format.width),\n height: numberOf(format.height),\n fps: numberOf(format.fps),\n vcodec,\n acodec,\n abr: numberOf(format.abr),\n vbr: numberOf(format.vbr),\n tbr: numberOf(format.tbr),\n filesize: numberOf(format.filesize),\n filesizeApprox: numberOf(format.filesize_approx),\n quality: numberOf(format.quality),\n audioOnly: hasAudio && !hasVideo,\n videoOnly: hasVideo && !hasAudio,\n hasVideo,\n hasAudio,\n language: stringOf(format.language),\n container: stringOf(format.container),\n };\n}\n\n/**\n * Maps the raw progress payload from the native `downloadEvent` into a\n * `DownloadProgress`, replacing any non-finite numbers with `undefined`.\n */\nexport function mapDownloadProgress(raw: unknown, taskId: string): DownloadProgress | null {\n const progress = asRecord(raw);\n if (!progress) return null;\n\n const percent = numberOf(progress.percent);\n const phaseRaw = stringOf(progress.phase);\n\n return {\n taskId,\n status: statusOf(progress.status),\n phase: phaseRaw === 'extracting' || phaseRaw === 'processing' ? phaseRaw : 'downloading',\n percent,\n downloadedBytes: numberOf(progress.downloadedBytes),\n totalBytes: numberOf(progress.totalBytes),\n speedBytesPerSecond: numberOf(progress.speedBytesPerSecond),\n etaSeconds: numberOf(progress.etaSeconds),\n filename: stringOf(progress.filename),\n };\n}\n\nfunction statusOf(value: unknown): DownloadProgress['status'] {\n const s = stringOf(value);\n switch (s) {\n case 'queued':\n case 'extracting':\n case 'downloading':\n case 'processing':\n case 'completed':\n case 'cancelled':\n case 'failed':\n return s;\n default:\n return 'downloading';\n }\n}\n\nfunction normalizeThumbnails(value: unknown, fallbackUrl?: string): Thumbnail[] {\n const result: Thumbnail[] = [];\n if (Array.isArray(value)) {\n for (const item of value) {\n const record = asRecord(item);\n const url = stringOf(record.url);\n if (!url) continue;\n result.push({\n url,\n width: numberOf(record.width),\n height: numberOf(record.height),\n resolution: stringOf(record.resolution),\n id: stringOf(record.id),\n });\n }\n }\n if (result.length === 0 && fallbackUrl) {\n result.push({ url: fallbackUrl });\n }\n return result;\n}\n\nfunction firstThumbnailUrl(thumbnails: Thumbnail[]): string | undefined {\n return thumbnails[0]?.url;\n}\n\nfunction stringOf(value: unknown): string | undefined {\n if (typeof value === 'string' && value.length > 0) return value;\n return undefined;\n}\n\nfunction numberOf(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value))) {\n return Number(value);\n }\n return undefined;\n}\n\nfunction asRecord(value: unknown): RawRecord {\n if (typeof value === 'object' && value !== null) return value as RawRecord;\n return {};\n}\n"]}
1
+ {"version":3,"file":"mappers.js","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mapping from the raw JSON produced by yt-dlp into the stable public types.\n *\n * Everything is defensive: unknown fields become `undefined`, never fake\n * values (see AGENTS.md §11, §69, §70).\n */\nimport type { DownloadProgress, Format, Thumbnail, VideoInfo } from './types';\n\ntype RawRecord = Record<string, unknown>;\n\nconst NONE_CODEC = 'none';\n\nexport function mapVideoInfo(raw: unknown): VideoInfo {\n const info = asRecord(raw);\n\n const formats = Array.isArray(info.formats) ? info.formats.map(mapFormat) : [];\n\n const liveStatus = stringOf(info.live_status);\n const thumbnails = normalizeThumbnails(info.thumbnails, stringOf(info.thumbnail));\n\n return {\n id: stringOf(info.id),\n title: stringOf(info.title),\n description: stringOf(info.description),\n uploader: stringOf(info.uploader),\n uploaderId: stringOf(info.uploader_id),\n uploaderUrl: stringOf(info.uploader_url),\n channel: stringOf(info.channel),\n channelId: stringOf(info.channel_id),\n channelUrl: stringOf(info.channel_url),\n webpageUrl: stringOf(info.webpage_url),\n originalUrl: stringOf(info.original_url),\n thumbnail: firstThumbnailUrl(thumbnails) ?? stringOf(info.thumbnail),\n thumbnails,\n duration: numberOf(info.duration),\n durationString: stringOf(info.duration_string),\n uploadDate: stringOf(info.upload_date),\n timestamp: numberOf(info.timestamp),\n viewCount: numberOf(info.view_count),\n likeCount: numberOf(info.like_count),\n commentCount: numberOf(info.comment_count),\n ageLimit: numberOf(info.age_limit),\n isLive: liveStatus === 'is_live',\n wasLive: liveStatus === 'was_live',\n extractor: stringOf(info.extractor),\n extractorKey: stringOf(info.extractor_key),\n webpageUrlDomain: stringOf(info.webpage_url_domain),\n formats,\n };\n}\n\nexport function mapFormat(raw: unknown): Format {\n const format = asRecord(raw);\n const vcodec = stringOf(format.vcodec);\n const acodec = stringOf(format.acodec);\n const hasVideo = vcodec !== undefined && vcodec.toLowerCase() !== NONE_CODEC;\n const hasAudio = acodec !== undefined && acodec.toLowerCase() !== NONE_CODEC;\n\n return {\n id: stringOf(format.format_id) ?? stringOf(format.id) ?? '',\n url: stringOf(format.url),\n ext: stringOf(format.ext),\n protocol: stringOf(format.protocol),\n format: stringOf(format.format),\n formatNote: stringOf(format.format_note),\n width: numberOf(format.width),\n height: numberOf(format.height),\n fps: numberOf(format.fps),\n vcodec,\n acodec,\n abr: numberOf(format.abr),\n vbr: numberOf(format.vbr),\n tbr: numberOf(format.tbr),\n filesize: numberOf(format.filesize),\n filesizeApprox: numberOf(format.filesize_approx),\n quality: numberOf(format.quality),\n audioOnly: hasAudio && !hasVideo,\n videoOnly: hasVideo && !hasAudio,\n hasVideo,\n hasAudio,\n language: stringOf(format.language),\n container: stringOf(format.container),\n };\n}\n\n/**\n * Maps the raw progress payload from the native `downloadEvent` into a\n * `DownloadProgress`, replacing any non-finite numbers with `undefined`.\n */\nexport function mapDownloadProgress(raw: unknown, taskId: string): DownloadProgress | null {\n if (typeof raw !== 'object' || raw === null) return null;\n const progress = raw as RawRecord;\n\n const percent = numberOf(progress.percent);\n const phaseRaw = stringOf(progress.phase);\n\n return {\n taskId,\n status: statusOf(progress.status),\n phase: phaseRaw === 'extracting' || phaseRaw === 'processing' ? phaseRaw : 'downloading',\n percent,\n downloadedBytes: numberOf(progress.downloadedBytes),\n totalBytes: numberOf(progress.totalBytes),\n speedBytesPerSecond: numberOf(progress.speedBytesPerSecond),\n etaSeconds: numberOf(progress.etaSeconds),\n filename: stringOf(progress.filename),\n };\n}\n\nfunction statusOf(value: unknown): DownloadProgress['status'] {\n const s = stringOf(value);\n switch (s) {\n case 'queued':\n case 'extracting':\n case 'downloading':\n case 'processing':\n case 'paused':\n case 'completed':\n case 'cancelled':\n case 'failed':\n return s;\n default:\n return 'downloading';\n }\n}\n\nfunction normalizeThumbnails(value: unknown, fallbackUrl?: string): Thumbnail[] {\n const result: Thumbnail[] = [];\n if (Array.isArray(value)) {\n for (const item of value) {\n const record = asRecord(item);\n const url = stringOf(record.url);\n if (!url) continue;\n result.push({\n url,\n width: numberOf(record.width),\n height: numberOf(record.height),\n resolution: stringOf(record.resolution),\n id: stringOf(record.id),\n });\n }\n }\n if (result.length === 0 && fallbackUrl) {\n result.push({ url: fallbackUrl });\n }\n return result;\n}\n\nfunction firstThumbnailUrl(thumbnails: Thumbnail[]): string | undefined {\n return thumbnails[0]?.url;\n}\n\nfunction stringOf(value: unknown): string | undefined {\n if (typeof value === 'string' && value.length > 0) return value;\n return undefined;\n}\n\nfunction numberOf(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value))) {\n return Number(value);\n }\n return undefined;\n}\n\nfunction asRecord(value: unknown): RawRecord {\n if (typeof value === 'object' && value !== null) return value as RawRecord;\n return {};\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { CookieOptions, DownloadOptions, ExtractOptions } from './types';
2
+ export declare function serializeExtractOptions(options: ExtractOptions | undefined): Record<string, unknown>;
3
+ export declare function serializeDownloadOptions(options: DownloadOptions): Record<string, unknown>;
4
+ export declare function serializeCookies(cookies: CookieOptions): Record<string, unknown>;
5
+ //# sourceMappingURL=serializers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializers.d.ts","sourceRoot":"","sources":["../src/serializers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,cAAc,GAAG,SAAS,GAClC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+C1F;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKhF"}