@postfetch/core 0.9.1 → 0.9.2

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
@@ -13,9 +13,11 @@ for (const item of result.items) {
13
13
 
14
14
  `postfetch(url, options?)` detects the platform and resolves its media into a typed `PostfetchResult` (URLs plus the headers needed to fetch them). It performs no side effects beyond the lookup — `download`, `downloadBlob`, `archive` and `toResponse` materialize the result.
15
15
 
16
- `downloadBlob(url, options?)` materializes an already-resolved media URL for
17
- clients that need an uploadable `Blob`. Pass the resolved item's headers for
18
- protected CDN URLs: `downloadBlob(item.url, { headers: item.headers })`. Set
16
+ `downloadBlob(itemOrUrl, options?)` materializes resolved media for clients that
17
+ need an uploadable `Blob`. Prefer `downloadBlob(item, { remux: true })` to
18
+ include separate audio, assemble HLS playlists and use the item's headers.
19
+ Passing only `item.url` fetches that URL alone and may omit separate audio;
20
+ for direct URLs, pass `{ headers: item.headers }` when needed. Set
19
21
  `remux: true` to return `{ blob, thumbnail, width, height, duration }`: a
20
22
  normalized MP4, upload thumbnail and calculated presentation metadata. Remuxing
21
23
  defaults to off, uses `ffmpeg` and `ffprobe` from `PATH` unless their paths are
@@ -50,31 +50,32 @@ export type Archive = {
50
50
  */
51
51
  export declare function download(item: MediaItem, options?: DownloadOptions): Promise<Response>;
52
52
  /**
53
- * Download an already-resolved media URL as a Blob.
53
+ * Download a resolved media item or direct media URL as a Blob.
54
54
  *
55
55
  * This is useful for consumers that need to upload media themselves instead of
56
- * passing its URL to a third party. When the resolved {@link MediaItem} carries
57
- * required CDN headers, pass them in the options object. Set `remux: true` to
56
+ * passing its URL to a third party. Pass the full {@link MediaItem} to include
57
+ * separate audio, HLS playlists and required headers. A direct URL only fetches
58
+ * that URL; pass its required CDN headers in the options object. Set `remux: true` to
58
59
  * normalize an MP4 with an FFmpeg stream copy; if FFmpeg is unavailable or the
59
60
  * remux or metadata extraction fails, the operation throws.
60
61
  *
61
- * @param url A direct media URL returned by a resolver.
62
+ * @param input A resolved media item (recommended) or direct media URL.
62
63
  * @param options Headers, fetch implementation and opt-in remux behavior.
63
64
  * @returns A Blob, or with `remux: true`, the normalized video and its metadata.
64
65
  *
65
66
  * @example Upload a video with FormData
66
67
  * ```ts
67
68
  * const [media] = (await postfetch(sourceUrl)).items;
68
- * const video = await downloadBlob(media.url, { headers: media.headers, remux: true });
69
+ * const video = await downloadBlob(media, { remux: true });
69
70
  * form.append("video", video.blob, media.filename);
70
71
  * form.append("thumbnail", video.thumbnail, "thumbnail.jpg");
71
72
  * ```
72
73
  */
73
- export declare function downloadBlob(url: string, options: DownloadBlobOptions & {
74
+ export declare function downloadBlob(input: string | MediaItem, options: DownloadBlobOptions & {
74
75
  remux: true;
75
76
  }): Promise<RemuxedVideo>;
76
77
  /** Download without remuxing and return the upstream media Blob. */
77
- export declare function downloadBlob(url: string, options?: DownloadBlobOptions & {
78
+ export declare function downloadBlob(input: string | MediaItem, options?: DownloadBlobOptions & {
78
79
  remux?: false;
79
80
  }): Promise<Blob>;
80
81
  /** @deprecated Pass headers and fetch in a single {@link DownloadBlobOptions} object. */
package/dist/index.js CHANGED
@@ -2947,12 +2947,12 @@ async function download(item, options = {}) {
2947
2947
  }
2948
2948
  return response;
2949
2949
  }
2950
- async function downloadBlob(url, optionsOrHeaders = {}, legacyOptions = {}) {
2950
+ async function downloadBlob(input, optionsOrHeaders = {}, legacyOptions = {}) {
2951
2951
  const modern = isDownloadBlobOptions(optionsOrHeaders);
2952
2952
  const options = modern ? optionsOrHeaders : legacyOptions;
2953
2953
  const headers = modern ? optionsOrHeaders.headers ?? {} : optionsOrHeaders;
2954
2954
  const net = createNet(options.fetch ?? globalThis.fetch);
2955
- const response = await net(url, { headers });
2955
+ const response = typeof input === "string" ? await net(input, { headers }) : await download({ ...input, headers: modern ? optionsOrHeaders.headers ?? input.headers : input.headers }, options);
2956
2956
  if (!response.ok || !response.body) {
2957
2957
  throw new PostfetchError(502, `download failed: ${response.status}`);
2958
2958
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postfetch/core",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Zero-dependency typed core that turns Facebook, Instagram, LinkedIn, Pinterest, Reddit, SoundCloud, TikTok, X and YouTube post URLs into media files.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/download.ts CHANGED
@@ -77,39 +77,40 @@ export async function download(item: MediaItem, options: DownloadOptions = {}):
77
77
  }
78
78
 
79
79
  /**
80
- * Download an already-resolved media URL as a Blob.
80
+ * Download a resolved media item or direct media URL as a Blob.
81
81
  *
82
82
  * This is useful for consumers that need to upload media themselves instead of
83
- * passing its URL to a third party. When the resolved {@link MediaItem} carries
84
- * required CDN headers, pass them in the options object. Set `remux: true` to
83
+ * passing its URL to a third party. Pass the full {@link MediaItem} to include
84
+ * separate audio, HLS playlists and required headers. A direct URL only fetches
85
+ * that URL; pass its required CDN headers in the options object. Set `remux: true` to
85
86
  * normalize an MP4 with an FFmpeg stream copy; if FFmpeg is unavailable or the
86
87
  * remux or metadata extraction fails, the operation throws.
87
88
  *
88
- * @param url A direct media URL returned by a resolver.
89
+ * @param input A resolved media item (recommended) or direct media URL.
89
90
  * @param options Headers, fetch implementation and opt-in remux behavior.
90
91
  * @returns A Blob, or with `remux: true`, the normalized video and its metadata.
91
92
  *
92
93
  * @example Upload a video with FormData
93
94
  * ```ts
94
95
  * const [media] = (await postfetch(sourceUrl)).items;
95
- * const video = await downloadBlob(media.url, { headers: media.headers, remux: true });
96
+ * const video = await downloadBlob(media, { remux: true });
96
97
  * form.append("video", video.blob, media.filename);
97
98
  * form.append("thumbnail", video.thumbnail, "thumbnail.jpg");
98
99
  * ```
99
100
  */
100
101
  export async function downloadBlob(
101
- url: string,
102
+ input: string | MediaItem,
102
103
  options: DownloadBlobOptions & { remux: true },
103
104
  ): Promise<RemuxedVideo>;
104
105
  /** Download without remuxing and return the upstream media Blob. */
105
106
  export async function downloadBlob(
106
- url: string,
107
+ input: string | MediaItem,
107
108
  options?: DownloadBlobOptions & { remux?: false },
108
109
  ): Promise<Blob>;
109
110
  /** @deprecated Pass headers and fetch in a single {@link DownloadBlobOptions} object. */
110
111
  export async function downloadBlob(url: string, headers?: HeadersInit, options?: DownloadOptions): Promise<Blob>;
111
112
  export async function downloadBlob(
112
- url: string,
113
+ input: string | MediaItem,
113
114
  optionsOrHeaders: DownloadBlobOptions | HeadersInit = {},
114
115
  legacyOptions: DownloadOptions = {},
115
116
  ): Promise<Blob | RemuxedVideo> {
@@ -117,7 +118,9 @@ export async function downloadBlob(
117
118
  const options = modern ? optionsOrHeaders : legacyOptions;
118
119
  const headers = modern ? optionsOrHeaders.headers ?? {} : optionsOrHeaders;
119
120
  const net = createNet(options.fetch ?? globalThis.fetch);
120
- const response = await net(url, { headers });
121
+ const response = typeof input === "string"
122
+ ? await net(input, { headers })
123
+ : await download({ ...input, headers: modern ? optionsOrHeaders.headers ?? input.headers : input.headers }, options);
121
124
  if (!response.ok || !response.body) {
122
125
  throw new PostfetchError(502, `download failed: ${response.status}`);
123
126
  }