bun-torrent 0.0.4-beta → 0.0.6

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 (94) hide show
  1. package/README.md +36 -5
  2. package/dist/client.d.ts +15 -17
  3. package/dist/client.js +23 -32
  4. package/dist/client.js.map +1 -1
  5. package/dist/configs/defaults.d.ts +29 -0
  6. package/dist/configs/defaults.js +30 -0
  7. package/dist/configs/defaults.js.map +1 -0
  8. package/dist/index.d.ts +2 -1
  9. package/dist/index.js +2 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/magnet/base32/errors.d.ts +8 -0
  12. package/dist/magnet/base32/errors.js +13 -0
  13. package/dist/magnet/base32/errors.js.map +1 -0
  14. package/dist/magnet/base32/index.d.ts +3 -0
  15. package/dist/magnet/base32/index.js +24 -0
  16. package/dist/magnet/base32/index.js.map +1 -0
  17. package/dist/magnet/index.d.ts +2 -0
  18. package/dist/magnet/index.js +3 -0
  19. package/dist/magnet/index.js.map +1 -0
  20. package/dist/magnet/parser/errors.d.ts +12 -0
  21. package/dist/magnet/parser/errors.js +17 -0
  22. package/dist/magnet/parser/errors.js.map +1 -0
  23. package/dist/magnet/parser/index.d.ts +8 -0
  24. package/dist/magnet/parser/index.js +74 -0
  25. package/dist/magnet/parser/index.js.map +1 -0
  26. package/dist/magnet/parser/meta.d.ts +2 -0
  27. package/dist/magnet/parser/meta.js +68 -0
  28. package/dist/magnet/parser/meta.js.map +1 -0
  29. package/dist/magnet/parser/types.d.ts +5 -0
  30. package/dist/magnet/parser/types.js +2 -0
  31. package/dist/magnet/parser/types.js.map +1 -0
  32. package/dist/peer/extended/connection.d.ts +30 -0
  33. package/dist/peer/extended/connection.js +143 -0
  34. package/dist/peer/extended/connection.js.map +1 -0
  35. package/dist/peer/extended/errors.d.ts +14 -0
  36. package/dist/peer/extended/errors.js +19 -0
  37. package/dist/peer/extended/errors.js.map +1 -0
  38. package/dist/peer/extended/index.d.ts +5 -0
  39. package/dist/peer/extended/index.js +4 -0
  40. package/dist/peer/extended/index.js.map +1 -0
  41. package/dist/peer/extended/metadata/assembler.d.ts +12 -0
  42. package/dist/peer/extended/metadata/assembler.js +44 -0
  43. package/dist/peer/extended/metadata/assembler.js.map +1 -0
  44. package/dist/peer/extended/metadata/index.d.ts +8 -0
  45. package/dist/peer/extended/metadata/index.js +74 -0
  46. package/dist/peer/extended/metadata/index.js.map +1 -0
  47. package/dist/peer/extended/metadata/messages.d.ts +6 -0
  48. package/dist/peer/extended/metadata/messages.js +20 -0
  49. package/dist/peer/extended/metadata/messages.js.map +1 -0
  50. package/dist/peer/extended/protocol.d.ts +8 -0
  51. package/dist/peer/extended/protocol.js +31 -0
  52. package/dist/peer/extended/protocol.js.map +1 -0
  53. package/dist/peer/messages/index.js +5 -0
  54. package/dist/peer/messages/index.js.map +1 -1
  55. package/dist/peer/messages/types.d.ts +8 -2
  56. package/dist/peer/messages/types.js +1 -0
  57. package/dist/peer/messages/types.js.map +1 -1
  58. package/dist/peer/pool/index.js +4 -5
  59. package/dist/peer/pool/index.js.map +1 -1
  60. package/dist/peer/session/index.d.ts +1 -1
  61. package/dist/peer/session/index.js +10 -5
  62. package/dist/peer/session/index.js.map +1 -1
  63. package/dist/torrent/bencode/decoder.d.ts +4 -0
  64. package/dist/torrent/bencode/decoder.js +9 -0
  65. package/dist/torrent/bencode/decoder.js.map +1 -1
  66. package/dist/torrent/download/manager.d.ts +4 -0
  67. package/dist/torrent/download/manager.js +44 -18
  68. package/dist/torrent/download/manager.js.map +1 -1
  69. package/dist/torrent/index.d.ts +1 -1
  70. package/dist/torrent/index.js +1 -1
  71. package/dist/torrent/index.js.map +1 -1
  72. package/dist/torrent/pieces/DefaultPlanner.d.ts +1 -1
  73. package/dist/torrent/pieces/DefaultPlanner.js +6 -2
  74. package/dist/torrent/pieces/DefaultPlanner.js.map +1 -1
  75. package/dist/torrent/pieces/index.d.ts +1 -1
  76. package/dist/torrent/pieces/index.js +1 -1
  77. package/dist/torrent/pieces/index.js.map +1 -1
  78. package/dist/torrent/pieces/types.d.ts +1 -1
  79. package/dist/torrent/pieces/utils.d.ts +1 -2
  80. package/dist/torrent/pieces/utils.js +3 -3
  81. package/dist/torrent/pieces/utils.js.map +1 -1
  82. package/dist/tracker/http.d.ts +1 -1
  83. package/dist/tracker/http.js +4 -4
  84. package/dist/tracker/http.js.map +1 -1
  85. package/dist/tracker/index.d.ts +1 -1
  86. package/dist/tracker/index.js +4 -4
  87. package/dist/tracker/index.js.map +1 -1
  88. package/dist/tracker/types.d.ts +1 -2
  89. package/dist/tracker/types.js +1 -1
  90. package/dist/tracker/types.js.map +1 -1
  91. package/dist/tracker/udp.d.ts +1 -1
  92. package/dist/tracker/udp.js +4 -3
  93. package/dist/tracker/udp.js.map +1 -1
  94. package/package.json +33 -33
package/README.md CHANGED
@@ -2,12 +2,10 @@
2
2
 
3
3
  A minimal Bun-native BitTorrent download-only client written in TypeScript.
4
4
 
5
- `bun-torrent` can parse `.torrent` files, announce to HTTP and UDP trackers, connect to peers, download pieces, validate piece hashes, and write the downloaded files to disk. The public API is intentionally small: create a `Client`, inspect a torrent when you need metadata, then call `download()`.
5
+ `bun-torrent` can parse `.torrent` files and tracker-backed magnet links, announce to HTTP and UDP trackers, connect to peers, download pieces, validate piece hashes, and write the downloaded files to disk. The public API is intentionally small: create a `Client`, inspect a torrent when you need metadata, then call `download()`.
6
6
 
7
7
  It has no runtime dependencies.
8
8
 
9
- > This package is currently beta software. The API can still change before a stable release.
10
-
11
9
  ## Requirements
12
10
 
13
11
  - Bun `>= 1.3.0`
@@ -15,13 +13,13 @@ It has no runtime dependencies.
15
13
  ## Installation
16
14
 
17
15
  ```bash
18
- bun add bun-torrent@beta
16
+ bun add bun-torrent
19
17
  ```
20
18
 
21
19
  or:
22
20
 
23
21
  ```bash
24
- npm install bun-torrent@beta
22
+ npm install bun-torrent
25
23
  ```
26
24
 
27
25
  ## Basic Usage
@@ -111,6 +109,39 @@ console.log(metadata.files);
111
109
 
112
110
  Torrent file input can be a file path, `Uint8Array`, or `ArrayBuffer`.
113
111
 
112
+ ## Magnet Links
113
+
114
+ Magnet links are supported when they include at least one HTTP, HTTPS, or UDP tracker through the `tr` parameter. Metadata is fetched from peers with the `ut_metadata` extension before the normal download flow starts.
115
+
116
+ ```ts
117
+ const magnet =
118
+ 'magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567' +
119
+ '&dn=file.bin' +
120
+ '&tr=udp%3A%2F%2Ftracker.example.com%3A6969%2Fannounce';
121
+
122
+ const metadata = await client.inspect({ magnet });
123
+
124
+ console.log(metadata.name);
125
+ console.log(metadata.files);
126
+
127
+ const torrent = await client.download(
128
+ { magnet },
129
+ {
130
+ outputDirectory: './downloads',
131
+ },
132
+ );
133
+
134
+ await torrent.done;
135
+ ```
136
+
137
+ Supported magnet fields:
138
+
139
+ - `xt=urn:btih:<infoHash>`: required. Hex-encoded 40-character info hashes and base32 32-character info hashes are supported.
140
+ - `dn`: optional display name.
141
+ - `tr`: optional tracker URL. Multiple `tr` parameters are supported.
142
+
143
+ Trackerless magnets are not supported yet because DHT peer discovery is not implemented. A magnet without `tr` currently fails during inspection with a DHT-not-implemented error.
144
+
114
145
  ## Download Options
115
146
 
116
147
  ```ts
package/dist/client.d.ts CHANGED
@@ -22,27 +22,25 @@ export type ClientConfig = {
22
22
  targetConnections?: number;
23
23
  trackerTimeoutMs?: number;
24
24
  };
25
- export declare const DEFAULT_CLIENT_CONFIG: {
26
- readonly maxInFlightRequestsPerPeer: 20;
27
- readonly maxConnecting: 30;
28
- readonly minConnections: 0;
29
- readonly peerConnectTimeoutMs: 5000;
30
- readonly progressEvents: "piece";
31
- readonly requestTimeoutMs: 15000;
32
- readonly seed: false;
33
- readonly speedSampleIntervalMs: 500;
34
- readonly targetConnections: 20;
35
- readonly trackerTimeoutMs: 5000;
25
+ type InspectInput = {
26
+ torrentFile: string | Uint8Array | ArrayBuffer;
27
+ magnet?: undefined | null;
28
+ meta?: null;
29
+ } | {
30
+ magnet: string;
31
+ torrentFile?: undefined | null;
32
+ meta?: null;
36
33
  };
34
+ type DownloadInput = {
35
+ meta: TorrentMetadata;
36
+ } | InspectInput;
37
37
  export declare class Client {
38
38
  private readonly config;
39
39
  private readonly peerId;
40
40
  constructor(config?: ClientConfig);
41
- download(input: {
42
- torrentFile: string | Uint8Array | ArrayBuffer;
43
- }, options?: DownloadOptions): Promise<Torrent>;
44
- inspect(input: {
45
- torrentFile: string | Uint8Array | ArrayBuffer;
41
+ download(input: DownloadInput, options?: DownloadOptions): Promise<Torrent>;
42
+ inspect(input: InspectInput, options?: {
43
+ timeout?: number;
46
44
  }): Promise<TorrentMetadata>;
47
45
  private trackPeers;
48
46
  }
@@ -63,5 +61,5 @@ export type DownloadOptions = {
63
61
  trackerTimeoutMs?: number;
64
62
  };
65
63
  export type TorrentFileInput = string | Uint8Array | ArrayBuffer;
66
- export declare const readTorrentFile: (input: TorrentFileInput) => Promise<Uint8Array>;
64
+ export declare const readTorrentFile: (input: unknown) => Promise<Uint8Array>;
67
65
  export { Client as TorrentClient };
package/dist/client.js CHANGED
@@ -6,6 +6,9 @@ import { Torrent } from './torrent/session/index';
6
6
  import { ClientError, ClientErrorCode } from './client.error';
7
7
  import { trackPeers, TrackerError, TrackerErrorCode } from './tracker';
8
8
  import { getUnknownSelectedFiles, normalizeTorrentFileSelection } from './torrent/file-selection';
9
+ import { defaults } from './configs/defaults';
10
+ import { BunTorrentError } from './utils/errors';
11
+ import { parseMagnet } from './magnet';
9
12
  export var DownloadState;
10
13
  (function (DownloadState) {
11
14
  DownloadState["PARSING"] = "parsing";
@@ -13,18 +16,6 @@ export var DownloadState;
13
16
  DownloadState["CONNECTING"] = "connecting";
14
17
  DownloadState["DOWNLOADING"] = "downloading";
15
18
  })(DownloadState || (DownloadState = {}));
16
- export const DEFAULT_CLIENT_CONFIG = {
17
- maxInFlightRequestsPerPeer: 20,
18
- maxConnecting: 30,
19
- minConnections: 0,
20
- peerConnectTimeoutMs: 5_000,
21
- progressEvents: 'piece',
22
- requestTimeoutMs: 15_000,
23
- seed: false,
24
- speedSampleIntervalMs: 500,
25
- targetConnections: 20,
26
- trackerTimeoutMs: 5_000,
27
- };
28
19
  export class Client {
29
20
  config;
30
21
  peerId;
@@ -34,7 +25,7 @@ export class Client {
34
25
  }
35
26
  async download(input, options = {}) {
36
27
  options.onChangeState?.(DownloadState.PARSING);
37
- const meta = await this.inspect(input);
28
+ const meta = input.meta ?? (await this.inspect(input, { timeout: options.trackerTimeoutMs }));
38
29
  const downloadConfig = resolveDownloadConfig(this.config, options);
39
30
  assertValidFileSelection(meta, downloadConfig.files);
40
31
  options.onChangeState?.(DownloadState.TRACKING);
@@ -61,9 +52,15 @@ export class Client {
61
52
  speedSampleIntervalMs: downloadConfig.speedSampleIntervalMs,
62
53
  }), normalizeTorrentFileSelection(downloadConfig.files), downloadConfig.seed);
63
54
  }
64
- async inspect(input) {
65
- const bytes = await readTorrentFile(input.torrentFile);
66
- return parseTorrent(bytes);
55
+ async inspect(input, options) {
56
+ if ('torrentFile' in input && input.torrentFile !== undefined) {
57
+ const bytes = await readTorrentFile(input.torrentFile);
58
+ return parseTorrent(bytes);
59
+ }
60
+ if ('magnet' in input && input.magnet !== undefined && input.magnet !== null) {
61
+ return parseMagnet(input.magnet, this.peerId, options);
62
+ }
63
+ throw new BunTorrentError('No input provided', 'NO_INPUT');
67
64
  }
68
65
  async trackPeers(meta, options, config) {
69
66
  try {
@@ -89,27 +86,21 @@ const resolveDownloadConfig = (config, options) => ({
89
86
  files: options.files ?? config.files ?? null,
90
87
  maxInFlightRequestsPerPeer: options.maxInFlightRequestsPerPeer ??
91
88
  config.maxInFlightRequestsPerPeer ??
92
- DEFAULT_CLIENT_CONFIG.maxInFlightRequestsPerPeer,
93
- maxConnecting: options.maxConnecting ?? config.maxConnecting ?? DEFAULT_CLIENT_CONFIG.maxConnecting,
94
- minConnections: options.minConnections ?? config.minConnections ?? DEFAULT_CLIENT_CONFIG.minConnections,
89
+ defaults.download.maxInFlightRequestsPerPeer,
90
+ maxConnecting: options.maxConnecting ?? config.maxConnecting ?? defaults.peers.maxConnecting,
91
+ minConnections: options.minConnections ?? config.minConnections ?? defaults.peers.minConnections,
95
92
  outputDirectory: options.outputDirectory ?? config.outputDirectory ?? process.cwd(),
96
93
  peerConnectTimeoutMs: options.peerConnectTimeoutMs ??
97
94
  config.peerConnectTimeoutMs ??
98
- DEFAULT_CLIENT_CONFIG.peerConnectTimeoutMs,
99
- progressEvents: options.progressEvents ?? config.progressEvents ?? DEFAULT_CLIENT_CONFIG.progressEvents,
100
- requestTimeoutMs: options.requestTimeoutMs ??
101
- config.requestTimeoutMs ??
102
- DEFAULT_CLIENT_CONFIG.requestTimeoutMs,
103
- seed: options.seed ?? config.seed ?? DEFAULT_CLIENT_CONFIG.seed,
95
+ defaults.peers.connectTimeoutMs,
96
+ progressEvents: options.progressEvents ?? config.progressEvents ?? defaults.progress.events,
97
+ requestTimeoutMs: options.requestTimeoutMs ?? config.requestTimeoutMs ?? defaults.download.requestTimeoutMs,
98
+ seed: options.seed ?? config.seed ?? defaults.download.seed,
104
99
  speedSampleIntervalMs: options.speedSampleIntervalMs ??
105
100
  config.speedSampleIntervalMs ??
106
- DEFAULT_CLIENT_CONFIG.speedSampleIntervalMs,
107
- targetConnections: options.targetConnections ??
108
- config.targetConnections ??
109
- DEFAULT_CLIENT_CONFIG.targetConnections,
110
- trackerTimeoutMs: options.trackerTimeoutMs ??
111
- config.trackerTimeoutMs ??
112
- DEFAULT_CLIENT_CONFIG.trackerTimeoutMs,
101
+ defaults.progress.speedSampleIntervalMs,
102
+ targetConnections: options.targetConnections ?? config.targetConnections ?? defaults.peers.targetConnections,
103
+ trackerTimeoutMs: options.trackerTimeoutMs ?? config.trackerTimeoutMs ?? defaults.trackers.timeoutMs,
113
104
  });
114
105
  const assertValidFileSelection = (metadata, files) => {
115
106
  const unknownFiles = getUnknownSelectedFiles(metadata, files);
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export declare const defaults: {
2
+ readonly pieces: {
3
+ readonly blockSize: number;
4
+ };
5
+ readonly peers: {
6
+ readonly targetConnections: 20;
7
+ readonly minConnections: 0;
8
+ readonly maxConnecting: 30;
9
+ readonly connectTimeoutMs: 5000;
10
+ };
11
+ readonly download: {
12
+ readonly maxInFlightRequestsPerPeer: 300;
13
+ readonly baseInFlightRequestsPerPeer: 8;
14
+ readonly requestTimeoutMs: 15000;
15
+ readonly seed: false;
16
+ };
17
+ readonly progress: {
18
+ readonly events: "piece";
19
+ readonly speedSampleIntervalMs: 500;
20
+ };
21
+ readonly trackers: {
22
+ readonly announcePort: 6881;
23
+ readonly timeoutMs: 5000;
24
+ };
25
+ readonly magnet: {
26
+ readonly trackerTimeoutMs: 3000;
27
+ readonly peerTimeoutMs: 5000;
28
+ };
29
+ };
@@ -0,0 +1,30 @@
1
+ export const defaults = {
2
+ pieces: {
3
+ blockSize: 16 * 1024,
4
+ },
5
+ peers: {
6
+ targetConnections: 20,
7
+ minConnections: 0,
8
+ maxConnecting: 30,
9
+ connectTimeoutMs: 5_000,
10
+ },
11
+ download: {
12
+ maxInFlightRequestsPerPeer: 300,
13
+ baseInFlightRequestsPerPeer: 8,
14
+ requestTimeoutMs: 15_000,
15
+ seed: false,
16
+ },
17
+ progress: {
18
+ events: 'piece',
19
+ speedSampleIntervalMs: 500,
20
+ },
21
+ trackers: {
22
+ announcePort: 6881,
23
+ timeoutMs: 5_000,
24
+ },
25
+ magnet: {
26
+ trackerTimeoutMs: 3_000,
27
+ peerTimeoutMs: 5_000,
28
+ },
29
+ };
30
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/configs/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACpB,MAAM,EAAE;QACJ,SAAS,EAAE,EAAE,GAAG,IAAI;KACvB;IACD,KAAK,EAAE;QACH,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,CAAC;QACjB,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,KAAK;KAC1B;IACD,QAAQ,EAAE;QACN,0BAA0B,EAAE,GAAG;QAC/B,2BAA2B,EAAE,CAAC;QAC9B,gBAAgB,EAAE,MAAM;QACxB,IAAI,EAAE,KAAK;KACd;IACD,QAAQ,EAAE;QACN,MAAM,EAAE,OAAO;QACf,qBAAqB,EAAE,GAAG;KAC7B;IACD,QAAQ,EAAE;QACN,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,KAAK;KACnB;IACD,MAAM,EAAE;QACJ,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE,KAAK;KACvB;CACK,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,10 +2,11 @@
2
2
  * Copyright (c) 2026 Nikola Nedeljkovic
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
- export { Client, DEFAULT_CLIENT_CONFIG, DownloadState, TorrentClient } from './client';
5
+ export { Client, DownloadState, TorrentClient } from './client';
6
6
  export { ClientError, ClientErrorCode } from './client.error';
7
7
  export type { ClientConfig, DownloadOptions, TorrentFileInput } from './client';
8
8
  export { Torrent, TorrentState, TorrentParseError, TorrentParseErrorCode, TorrentStorageError, TorrentStorageErrorCode, PiecePlannerError, PiecePlannerErrorCode, } from './torrent/index';
9
+ export { MagnetParseError, MagnetParseErrorCode, Base32DecoderError, Base32DecoderErrorCode, } from './magnet';
9
10
  export { PeerPoolError, PeerPoolErrorCode, PeerSessionError, PeerSessionErrorCode } from './peer';
10
11
  export { TrackerError, TrackerErrorCode } from './tracker';
11
12
  export type { DownloadProgress, DownloadProgressEventMode, TorrentFileSelection, TorrentFiles, TorrentMetadata, TorrentStats, TorrentStateChange, } from './torrent/index';
package/dist/index.js CHANGED
@@ -2,9 +2,10 @@
2
2
  * Copyright (c) 2026 Nikola Nedeljkovic
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
- export { Client, DEFAULT_CLIENT_CONFIG, DownloadState, TorrentClient } from './client';
5
+ export { Client, DownloadState, TorrentClient } from './client';
6
6
  export { ClientError, ClientErrorCode } from './client.error';
7
7
  export { Torrent, TorrentState, TorrentParseError, TorrentParseErrorCode, TorrentStorageError, TorrentStorageErrorCode, PiecePlannerError, PiecePlannerErrorCode, } from './torrent/index';
8
+ export { MagnetParseError, MagnetParseErrorCode, Base32DecoderError, Base32DecoderErrorCode, } from './magnet';
8
9
  export { PeerPoolError, PeerPoolErrorCode, PeerSessionError, PeerSessionErrorCode } from './peer';
9
10
  export { TrackerError, TrackerErrorCode } from './tracker';
10
11
  export { BunTorrentError } from './utils/errors';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAG9D,OAAO,EACH,OAAO,EACP,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,GACxB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAClG,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAa3D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAG9D,OAAO,EACH,OAAO,EACP,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,GACxB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACH,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,GACzB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAClG,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAa3D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { BunTorrentError } from '../../utils/errors';
2
+ export declare enum Base32DecoderErrorCode {
3
+ INVALID_CHAR = "INVALID_BASE32_CHAR"
4
+ }
5
+ export declare class Base32DecoderError extends BunTorrentError {
6
+ readonly field?: string | undefined;
7
+ constructor(code: Base32DecoderErrorCode, message: string, field?: string | undefined);
8
+ }
@@ -0,0 +1,13 @@
1
+ import { BunTorrentError } from '../../utils/errors';
2
+ export var Base32DecoderErrorCode;
3
+ (function (Base32DecoderErrorCode) {
4
+ Base32DecoderErrorCode["INVALID_CHAR"] = "INVALID_BASE32_CHAR";
5
+ })(Base32DecoderErrorCode || (Base32DecoderErrorCode = {}));
6
+ export class Base32DecoderError extends BunTorrentError {
7
+ field;
8
+ constructor(code, message, field) {
9
+ super(message, code);
10
+ this.field = field;
11
+ }
12
+ }
13
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/magnet/base32/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,CAAN,IAAY,sBAEX;AAFD,WAAY,sBAAsB;IAC9B,8DAAoC,CAAA;AACxC,CAAC,EAFW,sBAAsB,KAAtB,sBAAsB,QAEjC;AAED,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IAI/B;IAHpB,YACI,IAA4B,EAC5B,OAAe,EACC,KAAc;QAE9B,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAFL,UAAK,GAAL,KAAK,CAAS;IAGlC,CAAC;CACJ"}
@@ -0,0 +1,3 @@
1
+ import { Base32DecoderError, Base32DecoderErrorCode } from './errors';
2
+ export declare const decodeBase32: (str: string) => Uint8Array;
3
+ export { Base32DecoderError, Base32DecoderErrorCode };
@@ -0,0 +1,24 @@
1
+ import { Base32DecoderError, Base32DecoderErrorCode } from './errors';
2
+ const BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
3
+ export const decodeBase32 = (str) => {
4
+ const base32 = str.toUpperCase().replace(/=+$/, '');
5
+ let bits = 0;
6
+ let value = 0;
7
+ let index = 0;
8
+ const output = new Uint8Array(Math.floor((base32.length * 5) / 8));
9
+ for (const char of base32) {
10
+ const charIndex = BASE32_ALPHABET.indexOf(char);
11
+ if (charIndex === -1) {
12
+ throw new Base32DecoderError(Base32DecoderErrorCode.INVALID_CHAR, `Invalid base32 character: ${char}`);
13
+ }
14
+ value = (value << 5) | charIndex;
15
+ bits += 5;
16
+ if (bits >= 8) {
17
+ output[index++] = (value >> (bits - 8)) & 0xff;
18
+ bits -= 8;
19
+ }
20
+ }
21
+ return output;
22
+ };
23
+ export { Base32DecoderError, Base32DecoderErrorCode };
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/magnet/base32/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEtE,MAAM,eAAe,GAAG,kCAAkC,CAAC;AAE3D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAc,EAAE;IACpD,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEpD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAEnE,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,kBAAkB,CACxB,sBAAsB,CAAC,YAAY,EACnC,6BAA6B,IAAI,EAAE,CACtC,CAAC;QACN,CAAC;QAED,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;QACjC,IAAI,IAAI,CAAC,CAAC;QAEV,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YAC/C,IAAI,IAAI,CAAC,CAAC;QACd,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { decodeBase32, Base32DecoderError, Base32DecoderErrorCode } from './base32';
2
+ export { parseMagnet, MagnetParseError, MagnetParseErrorCode } from './parser';
@@ -0,0 +1,3 @@
1
+ export { decodeBase32, Base32DecoderError, Base32DecoderErrorCode } from './base32';
2
+ export { parseMagnet, MagnetParseError, MagnetParseErrorCode } from './parser';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/magnet/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { BunTorrentError } from '../../utils/errors';
2
+ export declare enum MagnetParseErrorCode {
3
+ INVALID_URI = "INVALID_MAGNET_URI",
4
+ INVALID_XT = "INVALID_XT_PARAM",
5
+ NOT_IMPLEMENTED = "NOT_IMPLEMENTED",
6
+ NO_METADATA = "NO_METADATA",
7
+ PARSING_FAILED = "METADATA_FAILED_TO_PARSE"
8
+ }
9
+ export declare class MagnetParseError extends BunTorrentError {
10
+ readonly field?: string | undefined;
11
+ constructor(code: MagnetParseErrorCode, message: string, field?: string | undefined);
12
+ }
@@ -0,0 +1,17 @@
1
+ import { BunTorrentError } from '../../utils/errors';
2
+ export var MagnetParseErrorCode;
3
+ (function (MagnetParseErrorCode) {
4
+ MagnetParseErrorCode["INVALID_URI"] = "INVALID_MAGNET_URI";
5
+ MagnetParseErrorCode["INVALID_XT"] = "INVALID_XT_PARAM";
6
+ MagnetParseErrorCode["NOT_IMPLEMENTED"] = "NOT_IMPLEMENTED";
7
+ MagnetParseErrorCode["NO_METADATA"] = "NO_METADATA";
8
+ MagnetParseErrorCode["PARSING_FAILED"] = "METADATA_FAILED_TO_PARSE";
9
+ })(MagnetParseErrorCode || (MagnetParseErrorCode = {}));
10
+ export class MagnetParseError extends BunTorrentError {
11
+ field;
12
+ constructor(code, message, field) {
13
+ super(message, code);
14
+ this.field = field;
15
+ }
16
+ }
17
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/magnet/parser/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,CAAN,IAAY,oBAMX;AAND,WAAY,oBAAoB;IAC5B,0DAAkC,CAAA;IAClC,uDAA+B,CAAA;IAC/B,2DAAmC,CAAA;IACnC,mDAA2B,CAAA;IAC3B,mEAA2C,CAAA;AAC/C,CAAC,EANW,oBAAoB,KAApB,oBAAoB,QAM/B;AAED,MAAM,OAAO,gBAAiB,SAAQ,eAAe;IAI7B;IAHpB,YACI,IAA0B,EAC1B,OAAe,EACC,KAAc;QAE9B,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAFL,UAAK,GAAL,KAAK,CAAS;IAGlC,CAAC;CACJ"}
@@ -0,0 +1,8 @@
1
+ import { type TorrentMetadata } from '../../torrent';
2
+ import { MagnetParseError, MagnetParseErrorCode } from './errors';
3
+ import type { ParsedMagnetURI } from './types';
4
+ export declare const parseMagnet: (magnet: string, peerId: Uint8Array, options?: {
5
+ timeout?: number;
6
+ }) => Promise<TorrentMetadata>;
7
+ export declare const parseMagnetURI: (uri: string) => ParsedMagnetURI;
8
+ export { MagnetParseError, MagnetParseErrorCode };
@@ -0,0 +1,74 @@
1
+ import { defaults } from '../../configs/defaults';
2
+ import { fetchMetadataFromPeer } from '../../peer/extended';
3
+ import {} from '../../torrent';
4
+ import { trackPeers } from '../../tracker';
5
+ import { decodeBase32 } from '../base32';
6
+ import { MagnetParseError, MagnetParseErrorCode } from './errors';
7
+ import { parseInfoDict } from './meta';
8
+ export const parseMagnet = async (magnet, peerId, options) => {
9
+ const data = parseMagnetURI(magnet);
10
+ if (data.trackers.length <= 0) {
11
+ throw new MagnetParseError(MagnetParseErrorCode.NOT_IMPLEMENTED, 'No trackers found, DHT is not yet implemented');
12
+ }
13
+ const peers = await trackPeers({
14
+ meta: {
15
+ infoHash: data.infoHash,
16
+ length: 0,
17
+ announce: undefined,
18
+ announceList: data.trackers.map((t) => [t]),
19
+ },
20
+ peerId: peerId,
21
+ timeoutMs: defaults.magnet.trackerTimeoutMs,
22
+ });
23
+ let raw;
24
+ try {
25
+ raw = await Promise.any(peers.map((p) => fetchMetadataFromPeer(p, data.infoHash, peerId, {
26
+ timeoutMs: options?.timeout ?? defaults.magnet.peerTimeoutMs,
27
+ })));
28
+ }
29
+ catch {
30
+ throw new MagnetParseError(MagnetParseErrorCode.NO_METADATA, 'Failed to fetch metadata from any peer');
31
+ }
32
+ try {
33
+ return parseInfoDict(raw, data.infoHash, undefined, data.trackers.map((t) => [t]));
34
+ }
35
+ catch {
36
+ throw new MagnetParseError(MagnetParseErrorCode.PARSING_FAILED, 'Failed to parse metadata from peer');
37
+ }
38
+ };
39
+ export const parseMagnetURI = (uri) => {
40
+ let url;
41
+ try {
42
+ url = new URL(uri);
43
+ }
44
+ catch {
45
+ throw new MagnetParseError(MagnetParseErrorCode.INVALID_URI, 'Invalid magnet URI');
46
+ }
47
+ if (url.protocol !== 'magnet:') {
48
+ throw new MagnetParseError(MagnetParseErrorCode.INVALID_URI, 'Invalid magnet URI scheme');
49
+ }
50
+ const params = new URLSearchParams(url.search);
51
+ const xt = params.get('xt');
52
+ const name = params.get('dn') ?? undefined;
53
+ const trackers = params.getAll('tr');
54
+ if (!xt?.startsWith('urn:btih:'))
55
+ throw new MagnetParseError(MagnetParseErrorCode.INVALID_XT, 'Invalid xt parameter');
56
+ const raw = xt.slice(9);
57
+ if (raw.length !== 40 && raw.length !== 32) {
58
+ throw new MagnetParseError(MagnetParseErrorCode.INVALID_XT, 'Invalid info hash length');
59
+ }
60
+ if (raw.length === 40 && !isHex(raw)) {
61
+ throw new MagnetParseError(MagnetParseErrorCode.INVALID_XT, 'Invalid hex info hash');
62
+ }
63
+ return {
64
+ infoHash: raw.length === 40 ? Uint8Array.fromHex(raw) : decodeBase32(raw),
65
+ name,
66
+ trackers,
67
+ };
68
+ };
69
+ const isHex = (str) => {
70
+ const hexRegex = /^[0-9a-fA-F]+$/;
71
+ return hexRegex.test(str) && str.length === 40;
72
+ };
73
+ export { MagnetParseError, MagnetParseErrorCode };
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/magnet/parser/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { TorrentMetadata } from '../../torrent';
2
+ export declare const parseInfoDict: (dict: unknown, infoHash: Uint8Array, announce?: string, announceList?: string[][]) => TorrentMetadata;
@@ -0,0 +1,68 @@
1
+ const textDecoder = new TextDecoder();
2
+ export const parseInfoDict = (dict, infoHash, announce, announceList = []) => {
3
+ if (!(dict instanceof Map))
4
+ throw new Error('Info dict must be a Map');
5
+ const name = dict.get('name');
6
+ if (!(name instanceof Uint8Array))
7
+ throw new Error('Missing name');
8
+ const pieceLength = dict.get('piece length');
9
+ if (typeof pieceLength !== 'number')
10
+ throw new Error('Missing piece length');
11
+ const piecesRaw = dict.get('pieces');
12
+ if (!(piecesRaw instanceof Uint8Array) || piecesRaw.byteLength % 20 !== 0)
13
+ throw new Error('Invalid pieces');
14
+ const pieces = [];
15
+ for (let i = 0; i < piecesRaw.byteLength; i += 20) {
16
+ pieces.push(piecesRaw.subarray(i, i + 20));
17
+ }
18
+ const filesRaw = dict.get('files');
19
+ if (Array.isArray(filesRaw)) {
20
+ let offset = 0;
21
+ const files = filesRaw.map((f) => {
22
+ if (!(f instanceof Map))
23
+ throw new Error('Invalid file entry');
24
+ const length = f.get('length');
25
+ if (typeof length !== 'number')
26
+ throw new Error('Missing file length');
27
+ const path = f.get('path');
28
+ if (!Array.isArray(path))
29
+ throw new Error('Missing file path');
30
+ const file = {
31
+ path: path.map((p) => {
32
+ if (!(p instanceof Uint8Array))
33
+ throw new Error('Invalid path segment');
34
+ return textDecoder.decode(p);
35
+ }),
36
+ length,
37
+ offset,
38
+ };
39
+ offset += length;
40
+ return file;
41
+ });
42
+ return {
43
+ announce,
44
+ announceList,
45
+ infoHash,
46
+ name: textDecoder.decode(name),
47
+ pieceLength,
48
+ pieces,
49
+ length: offset,
50
+ files,
51
+ };
52
+ }
53
+ // single-file
54
+ const length = dict.get('length');
55
+ if (typeof length !== 'number')
56
+ throw new Error('Missing length');
57
+ return {
58
+ announce,
59
+ announceList,
60
+ infoHash,
61
+ name: textDecoder.decode(name),
62
+ pieceLength,
63
+ pieces,
64
+ length,
65
+ files: [{ path: [textDecoder.decode(name)], length, offset: 0 }],
66
+ };
67
+ };
68
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../../src/magnet/parser/meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type ParsedMagnetURI = {
2
+ infoHash: Uint8Array;
3
+ name?: string;
4
+ trackers: string[];
5
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/magnet/parser/types.ts"],"names":[],"mappings":""}