@postfetch/core 0.6.0 → 0.8.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.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Zero-dependency typed core that turns Facebook, Instagram, LinkedIn, Pinterest, Reddit, SoundCloud, TikTok, X and YouTube post URLs into media files. Part of [postfetch](https://github.com/chelokot/postfetch).
4
4
 
5
5
  ```ts
6
- import { postfetch, download, archive, toResponse, PostfetchError } from "@postfetch/core";
6
+ import { postfetch, download, downloadBlob, archive, toResponse, PostfetchError } from "@postfetch/core";
7
7
 
8
8
  const result = await postfetch("https://vt.tiktok.com/ZSxpHvCUM/");
9
9
  for (const item of result.items) {
@@ -11,10 +11,19 @@ for (const item of result.items) {
11
11
  }
12
12
  ```
13
13
 
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`, `archive` and `toResponse` turn the result into bytes or an HTTP `Response`.
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
- - `PostfetchOptions` — `{ fetch?: typeof fetch; preferredWidth?: number }`. Inject `fetch` to unit-test resolvers offline.
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
19
+ `remux: true` to normalize an MP4 with an FFmpeg stream copy (fast-start,
20
+ non-negative timestamps, no edit list). Remuxing defaults to off, uses `ffmpeg`
21
+ from `PATH` unless `ffmpegPath` is set, and falls back to the original Blob on
22
+ failure. The legacy `(url, headers?, options?)` overload remains supported.
23
+
24
+ - `PostfetchOptions` — `{ fetch?: typeof fetch; preferredWidth?: number; tryMaxBytes?: number }`. `tryMaxBytes` is a soft byte cap. X probes every MP4 variant and selects the highest-quality complete result that fits, falling back to its smallest variants when none do. Other platforms return a smaller available rendition when possible and otherwise keep the normal result. Inject `fetch` to unit-test resolvers offline.
17
25
  - Every request rotates a consistent browser/app fingerprint, so a fixed user-agent never gets the whole fleet blocked.
18
- - No runtime dependencies, no `ffmpeg` / `yt-dlp`, no cookies.
26
+ - No runtime dependencies, no `yt-dlp`, no cookies. `ffmpeg` is only used when
27
+ the opt-in `downloadBlob(..., { remux: true })` path is requested.
19
28
 
20
29
  See the [root README](https://github.com/chelokot/postfetch#readme) for the full API table, supported inputs and the fingerprint design.
@@ -4,6 +4,15 @@ export type DownloadOptions = {
4
4
  /** Custom `fetch` implementation. Defaults to the global `fetch`. */
5
5
  fetch?: typeof fetch;
6
6
  };
7
+ /** Options for {@link downloadBlob}. */
8
+ export type DownloadBlobOptions = DownloadOptions & {
9
+ /** Command used for opt-in MP4 remuxing. Defaults to `ffmpeg` from `PATH`. */
10
+ ffmpegPath?: string;
11
+ /** Headers required by the resolved media URL. */
12
+ headers?: HeadersInit;
13
+ /** Normalize an MP4 container with FFmpeg. Defaults to `false`. */
14
+ remux?: boolean;
15
+ };
7
16
  /** A zip archive produced by {@link archive}. */
8
17
  export type Archive = {
9
18
  /** The zip bytes (store mode, built in-process). */
@@ -30,6 +39,29 @@ export type Archive = {
30
39
  * ```
31
40
  */
32
41
  export declare function download(item: MediaItem, options?: DownloadOptions): Promise<Response>;
42
+ /**
43
+ * Download an already-resolved media URL as a Blob.
44
+ *
45
+ * This is useful for consumers that need to upload media themselves instead of
46
+ * passing its URL to a third party. When the resolved {@link MediaItem} carries
47
+ * required CDN headers, pass them in the options object. Set `remux: true` to
48
+ * normalize an MP4 with an FFmpeg stream copy; if FFmpeg is unavailable or the
49
+ * remux fails, the original Blob is returned.
50
+ *
51
+ * @param url A direct media URL returned by a resolver.
52
+ * @param options Headers, fetch implementation and opt-in remux behavior.
53
+ * @returns The downloaded media as a Blob.
54
+ *
55
+ * @example Upload a video with FormData
56
+ * ```ts
57
+ * const [media] = (await postfetch(sourceUrl)).items;
58
+ * const blob = await downloadBlob(media.url, { headers: media.headers, remux: true });
59
+ * form.append("video", blob, media.filename);
60
+ * ```
61
+ */
62
+ export declare function downloadBlob(url: string, options?: DownloadBlobOptions): Promise<Blob>;
63
+ /** @deprecated Pass headers and fetch in a single {@link DownloadBlobOptions} object. */
64
+ export declare function downloadBlob(url: string, headers?: HeadersInit, options?: DownloadOptions): Promise<Blob>;
33
65
  /**
34
66
  * Download every item of a result and zip them in-process (store mode).
35
67
  *
package/dist/index.d.ts CHANGED
@@ -5,8 +5,8 @@
5
5
  * URLs to typed {@link MediaItem}s. Zero dependencies, only Web-standard APIs
6
6
  * (`fetch`, `Response`, `URL`, `crypto`) — so it runs on Deno, Node, Bun,
7
7
  * Cloudflare Workers and browsers alike. It only resolves the media; the
8
- * {@link download}, {@link archive} and {@link toResponse} helpers turn a result
9
- * into bytes or a `Response`.
8
+ * {@link download}, {@link downloadBlob}, {@link archive} and {@link toResponse}
9
+ * helpers turn a result into bytes, a `Blob`, or a `Response`.
10
10
  *
11
11
  * @example Resolve a reel and save the video
12
12
  * ```ts
@@ -20,6 +20,6 @@
20
20
  * @module
21
21
  */
22
22
  export { postfetch, detect, type PostfetchOptions } from "./postfetch";
23
- export { download, archive, toResponse, type Archive, type DownloadOptions } from "./download";
23
+ export { download, downloadBlob, archive, toResponse, type Archive, type DownloadBlobOptions, type DownloadOptions, } from "./download";
24
24
  export { PostfetchError } from "./internal";
25
- export type { InstagramExtra, MediaItem, MediaKind, PinterestExtra, Platform, PlatformResult, PostAuthor, PostfetchReason, PostfetchResult, PostMetadata, RedditExtra, SoundcloudExtra, TiktokExtra, TwitterExtra, YoutubeExtra, } from "./internal";
25
+ export type { InstagramExtra, MediaItem, MediaKind, PinterestExtra, Platform, PlatformResult, PostAuthor, PostfetchReason, PostfetchResult, PostMetadata, RedditExtra, SoundcloudExtra, TiktokExtra, TwitterExtra, TwitterQuotedTweet, YoutubeExtra, } from "./internal";