@media-engine/providers 0.1.0 → 1.0.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 (214) hide show
  1. package/README.md +149 -242
  2. package/README.ru.md +204 -0
  3. package/dist/aniliberty-streaming/client.d.ts +33 -0
  4. package/dist/aniliberty-streaming/client.js +188 -0
  5. package/dist/aniliberty-streaming/client.js.map +1 -0
  6. package/dist/aniliberty-streaming/config.d.ts +24 -0
  7. package/dist/aniliberty-streaming/config.js +61 -0
  8. package/dist/aniliberty-streaming/config.js.map +1 -0
  9. package/dist/aniliberty-streaming/index.d.ts +4 -0
  10. package/dist/aniliberty-streaming/index.js +45 -0
  11. package/dist/aniliberty-streaming/index.js.map +1 -0
  12. package/dist/aniliberty-streaming/mapping.d.ts +3 -0
  13. package/dist/aniliberty-streaming/mapping.js +87 -0
  14. package/dist/aniliberty-streaming/mapping.js.map +1 -0
  15. package/dist/aniliberty-streaming/matching.d.ts +4 -0
  16. package/dist/aniliberty-streaming/matching.js +44 -0
  17. package/dist/aniliberty-streaming/matching.js.map +1 -0
  18. package/dist/anilist/graphql.d.ts +2 -0
  19. package/dist/anilist/graphql.js +135 -0
  20. package/dist/anilist/graphql.js.map +1 -0
  21. package/dist/anilist/index.js +11 -6
  22. package/dist/anilist/index.js.map +1 -1
  23. package/dist/bitsearch-torrent/client.d.ts +19 -0
  24. package/dist/bitsearch-torrent/client.js +181 -0
  25. package/dist/bitsearch-torrent/client.js.map +1 -0
  26. package/dist/bitsearch-torrent/config.d.ts +26 -0
  27. package/dist/bitsearch-torrent/config.js +74 -0
  28. package/dist/bitsearch-torrent/config.js.map +1 -0
  29. package/dist/bitsearch-torrent/index.d.ts +4 -0
  30. package/dist/bitsearch-torrent/index.js +35 -0
  31. package/dist/bitsearch-torrent/index.js.map +1 -0
  32. package/dist/bitsearch-torrent/mapping.d.ts +3 -0
  33. package/dist/bitsearch-torrent/mapping.js +53 -0
  34. package/dist/bitsearch-torrent/mapping.js.map +1 -0
  35. package/dist/bitsearch-torrent/matching.d.ts +3 -0
  36. package/dist/bitsearch-torrent/matching.js +13 -0
  37. package/dist/bitsearch-torrent/matching.js.map +1 -0
  38. package/dist/bitsearch-torrent/quota.d.ts +9 -0
  39. package/dist/bitsearch-torrent/quota.js +53 -0
  40. package/dist/bitsearch-torrent/quota.js.map +1 -0
  41. package/dist/cinemeta/index.js +53 -35
  42. package/dist/cinemeta/index.js.map +1 -1
  43. package/dist/ddbb-streaming/client.d.ts +24 -0
  44. package/dist/ddbb-streaming/client.js +98 -0
  45. package/dist/ddbb-streaming/client.js.map +1 -0
  46. package/dist/ddbb-streaming/config.d.ts +31 -0
  47. package/dist/ddbb-streaming/config.js +67 -0
  48. package/dist/ddbb-streaming/config.js.map +1 -0
  49. package/dist/ddbb-streaming/index.d.ts +4 -0
  50. package/dist/ddbb-streaming/index.js +53 -0
  51. package/dist/ddbb-streaming/index.js.map +1 -0
  52. package/dist/ddbb-streaming/mapping.d.ts +8 -0
  53. package/dist/ddbb-streaming/mapping.js +164 -0
  54. package/dist/ddbb-streaming/mapping.js.map +1 -0
  55. package/dist/ddbb-streaming/validation.d.ts +3 -0
  56. package/dist/ddbb-streaming/validation.js +84 -0
  57. package/dist/ddbb-streaming/validation.js.map +1 -0
  58. package/dist/experimental-streaming/index.js +55 -0
  59. package/dist/experimental-streaming/index.js.map +1 -1
  60. package/dist/flixhq-streaming/client.d.ts +12 -0
  61. package/dist/flixhq-streaming/client.js +103 -0
  62. package/dist/flixhq-streaming/client.js.map +1 -0
  63. package/dist/flixhq-streaming/index.d.ts +2 -2
  64. package/dist/flixhq-streaming/index.js +67 -106
  65. package/dist/flixhq-streaming/index.js.map +1 -1
  66. package/dist/imdb-dataset/index.d.ts +20 -5
  67. package/dist/imdb-dataset/index.js +83 -197
  68. package/dist/imdb-dataset/index.js.map +1 -1
  69. package/dist/imdb-dataset/memory-storage.d.ts +7 -0
  70. package/dist/imdb-dataset/memory-storage.js +168 -0
  71. package/dist/imdb-dataset/memory-storage.js.map +1 -0
  72. package/dist/imdb-dataset/sqlite-import.d.ts +24 -0
  73. package/dist/imdb-dataset/sqlite-import.js +298 -0
  74. package/dist/imdb-dataset/sqlite-import.js.map +1 -0
  75. package/dist/imdb-dataset/sqlite-runtime.d.ts +3 -0
  76. package/dist/imdb-dataset/sqlite-runtime.js +11 -0
  77. package/dist/imdb-dataset/sqlite-runtime.js.map +1 -0
  78. package/dist/imdb-dataset/sqlite-schema.d.ts +6 -0
  79. package/dist/imdb-dataset/sqlite-schema.js +88 -0
  80. package/dist/imdb-dataset/sqlite-schema.js.map +1 -0
  81. package/dist/imdb-dataset/sqlite-storage.d.ts +12 -0
  82. package/dist/imdb-dataset/sqlite-storage.js +208 -0
  83. package/dist/imdb-dataset/sqlite-storage.js.map +1 -0
  84. package/dist/imdb-dataset/storage.d.ts +33 -0
  85. package/dist/imdb-dataset/storage.js +2 -0
  86. package/dist/imdb-dataset/storage.js.map +1 -0
  87. package/dist/index.d.ts +7 -0
  88. package/dist/index.js +7 -0
  89. package/dist/index.js.map +1 -1
  90. package/dist/jacred-torrent/client.d.ts +24 -0
  91. package/dist/jacred-torrent/client.js +254 -0
  92. package/dist/jacred-torrent/client.js.map +1 -0
  93. package/dist/jacred-torrent/config.d.ts +24 -0
  94. package/dist/jacred-torrent/config.js +70 -0
  95. package/dist/jacred-torrent/config.js.map +1 -0
  96. package/dist/jacred-torrent/index.d.ts +4 -0
  97. package/dist/jacred-torrent/index.js +45 -0
  98. package/dist/jacred-torrent/index.js.map +1 -0
  99. package/dist/jacred-torrent/mapping.d.ts +3 -0
  100. package/dist/jacred-torrent/mapping.js +129 -0
  101. package/dist/jacred-torrent/mapping.js.map +1 -0
  102. package/dist/jacred-torrent/matching.d.ts +3 -0
  103. package/dist/jacred-torrent/matching.js +19 -0
  104. package/dist/jacred-torrent/matching.js.map +1 -0
  105. package/dist/kinobd/index.js +15 -33
  106. package/dist/kinobd/index.js.map +1 -1
  107. package/dist/kinobd-streaming/availability.d.ts +3 -0
  108. package/dist/kinobd-streaming/availability.js +179 -0
  109. package/dist/kinobd-streaming/availability.js.map +1 -0
  110. package/dist/kinobd-streaming/candidates.d.ts +32 -0
  111. package/dist/kinobd-streaming/candidates.js +282 -0
  112. package/dist/kinobd-streaming/candidates.js.map +1 -0
  113. package/dist/kinobd-streaming/config.d.ts +64 -0
  114. package/dist/kinobd-streaming/config.js +129 -0
  115. package/dist/kinobd-streaming/config.js.map +1 -0
  116. package/dist/kinobd-streaming/index.d.ts +3 -30
  117. package/dist/kinobd-streaming/index.js +2 -904
  118. package/dist/kinobd-streaming/index.js.map +1 -1
  119. package/dist/kinobd-streaming/players.d.ts +24 -0
  120. package/dist/kinobd-streaming/players.js +270 -0
  121. package/dist/kinobd-streaming/players.js.map +1 -0
  122. package/dist/kinobd-streaming/request-budget.d.ts +15 -0
  123. package/dist/kinobd-streaming/request-budget.js +61 -0
  124. package/dist/kinobd-streaming/request-budget.js.map +1 -0
  125. package/dist/kinobd-streaming/validation.d.ts +11 -0
  126. package/dist/kinobd-streaming/validation.js +170 -0
  127. package/dist/kinobd-streaming/validation.js.map +1 -0
  128. package/dist/magnetz-torrent/client.d.ts +16 -0
  129. package/dist/magnetz-torrent/client.js +235 -0
  130. package/dist/magnetz-torrent/client.js.map +1 -0
  131. package/dist/magnetz-torrent/config.d.ts +27 -0
  132. package/dist/magnetz-torrent/config.js +73 -0
  133. package/dist/magnetz-torrent/config.js.map +1 -0
  134. package/dist/magnetz-torrent/index.d.ts +4 -0
  135. package/dist/magnetz-torrent/index.js +35 -0
  136. package/dist/magnetz-torrent/index.js.map +1 -0
  137. package/dist/magnetz-torrent/mapping.d.ts +3 -0
  138. package/dist/magnetz-torrent/mapping.js +52 -0
  139. package/dist/magnetz-torrent/mapping.js.map +1 -0
  140. package/dist/magnetz-torrent/matching.d.ts +3 -0
  141. package/dist/magnetz-torrent/matching.js +5 -0
  142. package/dist/magnetz-torrent/matching.js.map +1 -0
  143. package/dist/magnetz-torrent/request-gate.d.ts +9 -0
  144. package/dist/magnetz-torrent/request-gate.js +48 -0
  145. package/dist/magnetz-torrent/request-gate.js.map +1 -0
  146. package/dist/package-version.d.ts +2 -0
  147. package/dist/package-version.js +5 -0
  148. package/dist/package-version.js.map +1 -0
  149. package/dist/shared/abort.d.ts +3 -0
  150. package/dist/shared/abort.js +30 -0
  151. package/dist/shared/abort.js.map +1 -0
  152. package/dist/shared/http.d.ts +13 -2
  153. package/dist/shared/http.js +77 -75
  154. package/dist/shared/http.js.map +1 -1
  155. package/dist/shared/index.d.ts +2 -0
  156. package/dist/shared/index.js +2 -0
  157. package/dist/shared/index.js.map +1 -1
  158. package/dist/shared/mapping.d.ts +5 -0
  159. package/dist/shared/mapping.js +32 -0
  160. package/dist/shared/mapping.js.map +1 -0
  161. package/dist/shared/options.d.ts +1 -0
  162. package/dist/shared/options.js +10 -0
  163. package/dist/shared/options.js.map +1 -0
  164. package/dist/shared/output-url.d.ts +2 -0
  165. package/dist/shared/output-url.js +50 -0
  166. package/dist/shared/output-url.js.map +1 -0
  167. package/dist/shared/rate-limit.d.ts +11 -0
  168. package/dist/shared/rate-limit.js +52 -0
  169. package/dist/shared/rate-limit.js.map +1 -0
  170. package/dist/shared/response-body.d.ts +6 -0
  171. package/dist/shared/response-body.js +109 -0
  172. package/dist/shared/response-body.js.map +1 -0
  173. package/dist/shared/retry.d.ts +10 -0
  174. package/dist/shared/retry.js +31 -0
  175. package/dist/shared/retry.js.map +1 -0
  176. package/dist/shared/safe-fetch.d.ts +14 -0
  177. package/dist/shared/safe-fetch.js +274 -0
  178. package/dist/shared/safe-fetch.js.map +1 -0
  179. package/dist/shared/torrent-release-matching.d.ts +7 -0
  180. package/dist/shared/torrent-release-matching.js +143 -0
  181. package/dist/shared/torrent-release-matching.js.map +1 -0
  182. package/dist/shared/torrent-release-metadata.d.ts +4 -0
  183. package/dist/shared/torrent-release-metadata.js +95 -0
  184. package/dist/shared/torrent-release-metadata.js.map +1 -0
  185. package/dist/shikimori/index.js +19 -11
  186. package/dist/shikimori/index.js.map +1 -1
  187. package/dist/tvmaze/index.d.ts +11 -0
  188. package/dist/tvmaze/index.js +274 -0
  189. package/dist/tvmaze/index.js.map +1 -0
  190. package/dist/wikidata/cache.d.ts +11 -0
  191. package/dist/wikidata/cache.js +30 -0
  192. package/dist/wikidata/cache.js.map +1 -0
  193. package/dist/wikidata/candidates.d.ts +12 -0
  194. package/dist/wikidata/candidates.js +67 -0
  195. package/dist/wikidata/candidates.js.map +1 -0
  196. package/dist/wikidata/client.d.ts +40 -0
  197. package/dist/wikidata/client.js +224 -0
  198. package/dist/wikidata/client.js.map +1 -0
  199. package/dist/wikidata/index.d.ts +3 -0
  200. package/dist/wikidata/index.js +34 -111
  201. package/dist/wikidata/index.js.map +1 -1
  202. package/dist/yts-torrent/client.d.ts +25 -0
  203. package/dist/yts-torrent/client.js +163 -0
  204. package/dist/yts-torrent/client.js.map +1 -0
  205. package/dist/yts-torrent/config.d.ts +22 -0
  206. package/dist/yts-torrent/config.js +57 -0
  207. package/dist/yts-torrent/config.js.map +1 -0
  208. package/dist/yts-torrent/index.d.ts +4 -0
  209. package/dist/yts-torrent/index.js +42 -0
  210. package/dist/yts-torrent/index.js.map +1 -0
  211. package/dist/yts-torrent/mapping.d.ts +4 -0
  212. package/dist/yts-torrent/mapping.js +107 -0
  213. package/dist/yts-torrent/mapping.js.map +1 -0
  214. package/package.json +23 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort.js","sourceRoot":"","sources":["../../src/shared/abort.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,oGAAoG;AACpG,MAAM,UAAU,wBAAwB,CACtC,OAAwC,EACxC,KAAc;IAEd,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,gFAAgF;AAChF,MAAM,UAAU,qBAAqB,CACnC,YAAoB,EACpB,MAA+B;IAE/B,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7E,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,YAAY,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,7 +1,11 @@
1
1
  import { ProviderError, type ProviderErrorCode } from "@media-engine/core";
2
2
  import type { ProviderContext } from "@media-engine/core";
3
+ import type { ProviderRateLimitGate } from "./rate-limit.js";
3
4
  export type ProviderFetch = (input: string | URL, init?: RequestInit) => Promise<Response>;
4
- export declare function normalizePublicHttpUrl(value: string | null | undefined): string | undefined;
5
+ export interface ProviderHttpScheduler {
6
+ setTimeout(callback: () => void, delayMs: number): unknown;
7
+ clearTimeout(handle: unknown): void;
8
+ }
5
9
  export interface FetchJsonOptions {
6
10
  provider: string;
7
11
  url: string | URL;
@@ -10,8 +14,15 @@ export interface FetchJsonOptions {
10
14
  fetch?: ProviderFetch;
11
15
  maxRetries?: number;
12
16
  retryDelayMs?: number;
17
+ maxRetryDelayMs?: number;
18
+ retryJitterRatio?: number;
19
+ maxResponseBytes?: number;
20
+ rateLimitGate?: ProviderRateLimitGate;
21
+ scheduler?: ProviderHttpScheduler;
13
22
  }
14
23
  export declare function fetchJson<T>(options: FetchJsonOptions): Promise<T>;
15
- export declare function parseJsonResponse<T>(provider: string, response: Response): Promise<T>;
24
+ export declare function parseJsonResponse<T>(provider: string, response: Response, maxResponseBytes?: number, signal?: AbortSignal): Promise<T>;
16
25
  export declare function mapProviderHttpError(provider: string, error: unknown): ProviderError;
17
26
  export declare function mapHttpStatusToProviderErrorCode(status: number): ProviderErrorCode;
27
+ export declare function mapHttpResponseToProviderError(provider: string, response: Response): ProviderError;
28
+ export declare function getProviderHttpStatus(error: unknown): number | undefined;
@@ -1,68 +1,32 @@
1
1
  import { ProviderError } from "@media-engine/core";
2
- // Accepts only remote HTTP targets that cannot directly address the local machine or LAN.
3
- // Принимает только удаленные HTTP-цели без прямого доступа к локальной машине или LAN.
4
- export function normalizePublicHttpUrl(value) {
5
- if (!value) {
6
- return undefined;
7
- }
8
- try {
9
- const url = new URL(value);
10
- if ((url.protocol !== "http:" && url.protocol !== "https:") ||
11
- url.username !== "" ||
12
- url.password !== "" ||
13
- isPrivateHostname(url.hostname)) {
14
- return undefined;
15
- }
16
- return url.href;
17
- }
18
- catch {
19
- return undefined;
20
- }
21
- }
22
- function isPrivateHostname(value) {
23
- const hostname = value
24
- .toLowerCase()
25
- .replace(/^\[|\]$/g, "")
26
- .replace(/\.$/, "");
27
- if (hostname === "localhost" ||
28
- hostname.endsWith(".localhost") ||
29
- hostname === "0.0.0.0" ||
30
- hostname === "::" ||
31
- hostname === "::1") {
32
- return true;
33
- }
34
- if (hostname.includes(":")) {
35
- const first = Number.parseInt(hostname.split(":")[0] ?? "", 16);
36
- return (hostname.startsWith("::ffff:") ||
37
- (first >= 0xfc00 && first <= 0xfdff) ||
38
- (first >= 0xfe80 && first <= 0xfebf));
39
- }
40
- const octets = hostname.split(".").map(Number);
41
- if (octets.length !== 4 ||
42
- octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) {
43
- return false;
44
- }
45
- const [first, second] = octets;
46
- return (first === 0 ||
47
- first === 10 ||
48
- first === 127 ||
49
- (first === 100 && second >= 64 && second <= 127) ||
50
- (first === 169 && second === 254) ||
51
- (first === 172 && second >= 16 && second <= 31) ||
52
- (first === 192 && second === 0) ||
53
- (first === 192 && second === 168) ||
54
- (first === 198 && (second === 18 || second === 19)) ||
55
- first >= 224);
56
- }
2
+ import { readBoundedResponseText } from "./response-body.js";
3
+ import { calculateRetryDelayMs, parseRetryAfterMs } from "./retry.js";
4
+ const DEFAULT_MAX_JSON_RESPONSE_BYTES = 4 * 1024 * 1024;
5
+ const defaultScheduler = {
6
+ setTimeout(callback, delayMs) {
7
+ return setTimeout(callback, delayMs);
8
+ },
9
+ clearTimeout(handle) {
10
+ clearTimeout(handle);
11
+ },
12
+ };
57
13
  // Reads JSON through fetch and maps failures to ProviderError.
58
14
  // Читает JSON через fetch и преобразует сбои в ProviderError.
59
15
  export async function fetchJson(options) {
60
16
  const maxRetries = options.maxRetries ?? 1;
61
17
  const retryDelayMs = options.retryDelayMs ?? 150;
62
- const timeout = createProviderTimeout(options.provider, options.context);
18
+ const maxRetryDelayMs = options.maxRetryDelayMs ?? 2_000;
19
+ const retryJitterRatio = options.retryJitterRatio ?? 0.2;
20
+ const maxResponseBytes = options.maxResponseBytes ?? DEFAULT_MAX_JSON_RESPONSE_BYTES;
21
+ if (!Number.isSafeInteger(maxResponseBytes) || maxResponseBytes <= 0) {
22
+ throw new TypeError("fetchJson maxResponseBytes must be a positive safe integer.");
23
+ }
24
+ const scheduler = options.scheduler ?? defaultScheduler;
25
+ const timeout = createProviderTimeout(options.provider, options.context, scheduler);
63
26
  const signal = mergeAbortSignals(options.context?.signal, timeout.controller.signal);
64
27
  const boundedOptions = {
65
28
  ...options,
29
+ maxResponseBytes,
66
30
  context: {
67
31
  ...options.context,
68
32
  signal,
@@ -74,15 +38,25 @@ export async function fetchJson(options) {
74
38
  try {
75
39
  while (attempt <= maxRetries) {
76
40
  try {
41
+ await options.rateLimitGate?.wait(signal);
77
42
  return await fetchJsonAttempt(boundedOptions);
78
43
  }
79
44
  catch (error) {
80
45
  const providerError = mapProviderHttpError(options.provider, error);
46
+ const retryDelay = calculateRetryDelayMs({
47
+ baseDelayMs: retryDelayMs,
48
+ attempt,
49
+ maxDelayMs: maxRetryDelayMs,
50
+ jitterRatio: retryJitterRatio,
51
+ randomValue: Math.random(),
52
+ retryAfterMs: getRetryAfterMs(providerError),
53
+ });
81
54
  lastError = providerError;
55
+ deferSharedRateLimit(options.rateLimitGate, providerError, retryDelay);
82
56
  if (!providerError.retryable || attempt >= maxRetries) {
83
57
  throw providerError;
84
58
  }
85
- await delay(getRetryDelayMs(retryDelayMs, attempt), signal);
59
+ await delay(retryDelay, signal, scheduler);
86
60
  attempt += 1;
87
61
  }
88
62
  }
@@ -96,7 +70,7 @@ export async function fetchJson(options) {
96
70
  // Выполняет одну попытку JSON HTTP с новым timeout signal.
97
71
  async function fetchJsonAttempt(options) {
98
72
  const fetchImpl = options.fetch ?? fetch;
99
- const timeout = createProviderTimeout(options.provider, options.context);
73
+ const timeout = createProviderTimeout(options.provider, options.context, options.scheduler ?? defaultScheduler);
100
74
  const signal = mergeAbortSignals(options.context?.signal, timeout.controller.signal);
101
75
  try {
102
76
  const response = await fetchImpl(options.url, {
@@ -104,9 +78,9 @@ async function fetchJsonAttempt(options) {
104
78
  signal,
105
79
  });
106
80
  if (!response.ok) {
107
- throw createHttpProviderError(options.provider, response.status);
81
+ throw mapHttpResponseToProviderError(options.provider, response);
108
82
  }
109
- return await parseJsonResponse(options.provider, response);
83
+ return await parseJsonResponse(options.provider, response, options.maxResponseBytes ?? DEFAULT_MAX_JSON_RESPONSE_BYTES, signal);
110
84
  }
111
85
  finally {
112
86
  timeout.clear();
@@ -114,9 +88,10 @@ async function fetchJsonAttempt(options) {
114
88
  }
115
89
  // Parses response JSON and maps invalid bodies to ProviderError.
116
90
  // Парсит JSON ответа и преобразует невалидное тело в ProviderError.
117
- export async function parseJsonResponse(provider, response) {
91
+ export async function parseJsonResponse(provider, response, maxResponseBytes = DEFAULT_MAX_JSON_RESPONSE_BYTES, signal) {
92
+ const text = await readBoundedResponseText(provider, response, maxResponseBytes, { signal });
118
93
  try {
119
- return (await response.json());
94
+ return JSON.parse(text);
120
95
  }
121
96
  catch (error) {
122
97
  throw new ProviderError({
@@ -176,18 +151,50 @@ export function mapHttpStatusToProviderErrorCode(status) {
176
151
  }
177
152
  // Creates a ProviderError from an HTTP response status.
178
153
  // Создает ProviderError из HTTP status ответа.
179
- function createHttpProviderError(provider, status) {
154
+ export function mapHttpResponseToProviderError(provider, response) {
155
+ const status = response.status;
180
156
  const code = mapHttpStatusToProviderErrorCode(status);
181
- return new ProviderError({
157
+ return new HttpProviderError({
182
158
  provider,
183
159
  code,
184
160
  message: `Provider "${provider}" returned HTTP ${status}.`,
185
161
  retryable: code === "PROVIDER_RATE_LIMITED" || code === "PROVIDER_UNAVAILABLE",
162
+ status,
163
+ retryAfterMs: parseRetryAfterMs(response.headers.get("retry-after")),
186
164
  });
187
165
  }
166
+ // Returns the HTTP status retained by errors created from provider responses.
167
+ // Возвращает HTTP status, сохраненный в ошибках из provider response.
168
+ export function getProviderHttpStatus(error) {
169
+ return error instanceof HttpProviderError ? error.status : undefined;
170
+ }
171
+ class HttpProviderError extends ProviderError {
172
+ status;
173
+ retryAfterMs;
174
+ constructor(options) {
175
+ super(options);
176
+ this.status = options.status;
177
+ this.retryAfterMs = options.retryAfterMs;
178
+ }
179
+ }
180
+ function getRetryAfterMs(error) {
181
+ return error instanceof HttpProviderError ? error.retryAfterMs : undefined;
182
+ }
183
+ function deferSharedRateLimit(gate, error, fallbackDelayMs) {
184
+ if (!gate || !(error instanceof HttpProviderError)) {
185
+ return;
186
+ }
187
+ if (error.code === "PROVIDER_RATE_LIMITED") {
188
+ gate.defer(error.retryAfterMs ?? fallbackDelayMs);
189
+ return;
190
+ }
191
+ if (error.retryAfterMs !== undefined) {
192
+ gate.defer(error.retryAfterMs);
193
+ }
194
+ }
188
195
  // Creates a timeout controller for provider HTTP calls.
189
196
  // Создает timeout controller для HTTP-вызовов провайдера.
190
- function createProviderTimeout(provider, context) {
197
+ function createProviderTimeout(provider, context, scheduler) {
191
198
  const controller = new AbortController();
192
199
  const timeoutMs = context?.timeoutMs;
193
200
  if (timeoutMs === undefined) {
@@ -213,13 +220,13 @@ function createProviderTimeout(provider, context) {
213
220
  },
214
221
  };
215
222
  }
216
- const timeout = setTimeout(() => {
223
+ const timeout = scheduler.setTimeout(() => {
217
224
  controller.abort(timeoutError);
218
225
  }, timeoutMs);
219
226
  return {
220
227
  controller,
221
228
  clear() {
222
- clearTimeout(timeout);
229
+ scheduler.clearTimeout(timeout);
223
230
  },
224
231
  };
225
232
  }
@@ -234,14 +241,9 @@ function isAbortError(error) {
234
241
  return ((error instanceof DOMException && error.name === "AbortError") ||
235
242
  (error instanceof Error && error.name === "AbortError"));
236
243
  }
237
- // Calculates a small linear backoff for provider retries.
238
- // Считает небольшой линейный backoff для provider retry.
239
- function getRetryDelayMs(baseDelayMs, attempt) {
240
- return Math.max(0, baseDelayMs * (attempt + 1));
241
- }
242
244
  // Waits before the next provider retry.
243
245
  // Ждет перед следующей provider retry.
244
- function delay(ms, signal) {
246
+ function delay(ms, signal, scheduler) {
245
247
  if (ms <= 0) {
246
248
  return Promise.resolve();
247
249
  }
@@ -250,12 +252,12 @@ function delay(ms, signal) {
250
252
  reject(signal.reason);
251
253
  return;
252
254
  }
253
- const timeout = setTimeout(() => {
255
+ const timeout = scheduler.setTimeout(() => {
254
256
  signal?.removeEventListener("abort", onAbort);
255
257
  resolve();
256
258
  }, ms);
257
259
  const onAbort = () => {
258
- clearTimeout(timeout);
260
+ scheduler.clearTimeout(timeout);
259
261
  reject(signal?.reason);
260
262
  };
261
263
  signal?.addEventListener("abort", onAbort, { once: true });
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/shared/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/shared/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA0B,MAAM,oBAAoB,CAAC;AAG3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,+BAA+B,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AA8BxD,MAAM,gBAAgB,GAA0B;IAC9C,UAAU,CAAC,QAAQ,EAAE,OAAO;QAC1B,OAAO,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,YAAY,CAAC,MAAM;QACjB,YAAY,CAAC,MAAuC,CAAC,CAAC;IACxD,CAAC;CACF,CAAC;AAEF,+DAA+D;AAC/D,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAI,OAAyB;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,GAAG,CAAC;IACjD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC;IACzD,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,GAAG,CAAC;IACzD,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,+BAA+B,CAAC;IAErF,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,gBAAgB,IAAI,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,SAAS,CAAC,6DAA6D,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,gBAAgB,CAAC;IACxD,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACrF,MAAM,cAAc,GAAqB;QACvC,GAAG,OAAO;QACV,gBAAgB;QAChB,OAAO,EAAE;YACP,GAAG,OAAO,CAAC,OAAO;YAClB,MAAM;YACN,SAAS,EAAE,SAAS;SACrB;KACF,CAAC;IACF,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,SAAoC,CAAC;IAEzC,IAAI,CAAC;QACH,OAAO,OAAO,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC1C,OAAO,MAAM,gBAAgB,CAAI,cAAc,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,aAAa,GAAG,oBAAoB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACpE,MAAM,UAAU,GAAG,qBAAqB,CAAC;oBACvC,WAAW,EAAE,YAAY;oBACzB,OAAO;oBACP,UAAU,EAAE,eAAe;oBAC3B,WAAW,EAAE,gBAAgB;oBAC7B,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE;oBAC1B,YAAY,EAAE,eAAe,CAAC,aAAa,CAAC;iBAC7C,CAAC,CAAC;gBAEH,SAAS,GAAG,aAAa,CAAC;gBAC1B,oBAAoB,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;gBAEvE,IAAI,CAAC,aAAa,CAAC,SAAS,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;oBACtD,MAAM,aAAa,CAAC;gBACtB,CAAC;gBAED,MAAM,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;gBAC3C,OAAO,IAAI,CAAC,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,0DAA0D;AAC1D,2DAA2D;AAC3D,KAAK,UAAU,gBAAgB,CAAI,OAAyB;IAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IACzC,MAAM,OAAO,GAAG,qBAAqB,CACnC,OAAO,CAAC,QAAQ,EAChB,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,SAAS,IAAI,gBAAgB,CACtC,CAAC;IACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAErF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE;YAC5C,GAAG,OAAO,CAAC,IAAI;YACf,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,8BAA8B,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,MAAM,iBAAiB,CAC5B,OAAO,CAAC,QAAQ,EAChB,QAAQ,EACR,OAAO,CAAC,gBAAgB,IAAI,+BAA+B,EAC3D,MAAM,CACP,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAgB,EAChB,QAAkB,EAClB,gBAAgB,GAAG,+BAA+B,EAClD,MAAoB;IAEpB,MAAM,IAAI,GAAG,MAAM,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAE7F,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CAAC;YACtB,QAAQ;YACR,IAAI,EAAE,2BAA2B;YACjC,OAAO,EAAE,aAAa,QAAQ,0BAA0B;YACxD,SAAS,EAAE,KAAK;YAChB,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,uDAAuD;AACvD,uDAAuD;AACvD,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,KAAc;IACnE,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,aAAa,CAAC;YACvB,QAAQ;YACR,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,aAAa,QAAQ,sBAAsB;YACpD,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,IAAI,aAAa,CAAC;YACvB,QAAQ;YACR,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,aAAa,CAAC;QACvB,QAAQ;QACR,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,aAAa,QAAQ,mBAAmB;QACjD,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;AACL,CAAC;AAED,yDAAyD;AACzD,2DAA2D;AAC3D,MAAM,UAAU,gCAAgC,CAAC,MAAc;IAC7D,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACrC,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;QAClB,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,wDAAwD;AACxD,+CAA+C;AAC/C,MAAM,UAAU,8BAA8B,CAC5C,QAAgB,EAChB,QAAkB;IAElB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/B,MAAM,IAAI,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;IAEtD,OAAO,IAAI,iBAAiB,CAAC;QAC3B,QAAQ;QACR,IAAI;QACJ,OAAO,EAAE,aAAa,QAAQ,mBAAmB,MAAM,GAAG;QAC1D,SAAS,EAAE,IAAI,KAAK,uBAAuB,IAAI,IAAI,KAAK,sBAAsB;QAC9E,MAAM;QACN,YAAY,EAAE,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;KACrE,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,sEAAsE;AACtE,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,OAAO,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC;AAWD,MAAM,iBAAkB,SAAQ,aAAa;IAClC,MAAM,CAAS;IACf,YAAY,CAAqB;IAE1C,YAAY,OAAiC;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC3C,CAAC;CACF;AAED,SAAS,eAAe,CAAC,KAAoB;IAC3C,OAAO,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAAuC,EACvC,KAAoB,EACpB,eAAuB;IAEvB,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,YAAY,iBAAiB,CAAC,EAAE,CAAC;QACnD,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,IAAI,eAAe,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,wDAAwD;AACxD,0DAA0D;AAC1D,SAAS,qBAAqB,CAC5B,QAAgB,EAChB,OAAoC,EACpC,SAAgC;IAEhC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,CAAC;IAErC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO;YACL,UAAU;YACV,KAAK;gBACH,OAAO;YACT,CAAC;SACF,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,aAAa,CAAC;QACrC,QAAQ;QACR,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,aAAa,QAAQ,sBAAsB;QACpD,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;IAEH,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC/B,OAAO;YACL,UAAU;YACV,KAAK;gBACH,OAAO;YACT,CAAC;SACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE;QACxC,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC,EAAE,SAAS,CAAC,CAAC;IAEd,OAAO;QACL,UAAU;QACV,KAAK;YACH,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,4DAA4D;AAC5D,4DAA4D;AAC5D,SAAS,iBAAiB,CACxB,cAAuC,EACvC,aAA0B;IAE1B,OAAO,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;AAC3F,CAAC;AAED,2DAA2D;AAC3D,iEAAiE;AACjE,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,CACL,CAAC,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC;QAC9D,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CACxD,CAAC;AACJ,CAAC;AAED,wCAAwC;AACxC,uCAAuC;AACvC,SAAS,KAAK,CACZ,EAAU,EACV,MAA+B,EAC/B,SAAgC;IAEhC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE;YACxC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1,3 @@
1
1
  export * from "./http.js";
2
+ export * from "./output-url.js";
3
+ export * from "./rate-limit.js";
@@ -1,2 +1,4 @@
1
1
  export * from "./http.js";
2
+ export * from "./output-url.js";
3
+ export * from "./rate-limit.js";
2
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Genre, Image, MediaType } from "@media-engine/core";
2
+ export declare function mapGenreNames(genres: string[] | undefined, source: string): Genre[] | undefined;
3
+ export declare function createProviderImage(url: string | null | undefined, type: Image["type"], source: string): Image | undefined;
4
+ export declare function normalizeProviderSearchText(value: string): string;
5
+ export declare function mapKinoBdMediaType(type: string | null | undefined): MediaType | undefined;
@@ -0,0 +1,32 @@
1
+ import { normalizeProviderOutputUrl } from "./output-url.js";
2
+ // Maps simple genre labels into normalized provider-attributed values.
3
+ // Преобразует простые названия жанров в нормализованные значения с источником.
4
+ export function mapGenreNames(genres, source) {
5
+ return genres?.map((name) => ({ name, source }));
6
+ }
7
+ // Creates one normalized provider-attributed image from a direct URL.
8
+ // Создает одно нормализованное изображение с источником из прямого URL.
9
+ export function createProviderImage(url, type, source) {
10
+ const normalizedUrl = normalizeProviderOutputUrl(url);
11
+ return normalizedUrl ? { url: normalizedUrl, type, source } : undefined;
12
+ }
13
+ // Normalizes text for conservative provider-local title comparisons.
14
+ // Нормализует текст для консервативного сравнения названий внутри провайдеров.
15
+ export function normalizeProviderSearchText(value) {
16
+ return value
17
+ .toLocaleLowerCase()
18
+ .replaceAll(/[^\p{L}\p{N}]+/gu, " ")
19
+ .trim();
20
+ }
21
+ // Maps KinoBD API type labels shared by metadata and streaming adapters.
22
+ // Преобразует общие для metadata и streaming метки типов KinoBD API.
23
+ export function mapKinoBdMediaType(type) {
24
+ if (type === "film") {
25
+ return "movie";
26
+ }
27
+ if (type === "serial" || type === "series") {
28
+ return "series";
29
+ }
30
+ return undefined;
31
+ }
32
+ //# sourceMappingURL=mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/shared/mapping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAE7D,uEAAuE;AACvE,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,MAA4B,EAAE,MAAc;IACxE,OAAO,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,sEAAsE;AACtE,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CACjC,GAA8B,EAC9B,IAAmB,EACnB,MAAc;IAEd,MAAM,aAAa,GAAG,0BAA0B,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1E,CAAC;AAED,qEAAqE;AACrE,+EAA+E;AAC/E,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACvD,OAAO,KAAK;SACT,iBAAiB,EAAE;SACnB,UAAU,CAAC,kBAAkB,EAAE,GAAG,CAAC;SACnC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,yEAAyE;AACzE,qEAAqE;AACrE,MAAM,UAAU,kBAAkB,CAAC,IAA+B;IAChE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function resolveBoundedIntegerOption(value: number | undefined, fallback: number, name: string, min: number, max: number): number;
@@ -0,0 +1,10 @@
1
+ // Resolves a bounded integer option and fails early on unsafe provider configuration.
2
+ // Выбирает ограниченную integer-опцию и сразу отклоняет небезопасную конфигурацию провайдера.
3
+ export function resolveBoundedIntegerOption(value, fallback, name, min, max) {
4
+ const normalized = value ?? fallback;
5
+ if (!Number.isSafeInteger(normalized) || normalized < min || normalized > max) {
6
+ throw new RangeError(`${name} must be an integer between ${min} and ${max}.`);
7
+ }
8
+ return normalized;
9
+ }
10
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/shared/options.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,8FAA8F;AAC9F,MAAM,UAAU,2BAA2B,CACzC,KAAyB,EACzB,QAAgB,EAChB,IAAY,EACZ,GAAW,EACX,GAAW;IAEX,MAAM,UAAU,GAAG,KAAK,IAAI,QAAQ,CAAC;IAErC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,GAAG,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;QAC9E,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,+BAA+B,GAAG,QAAQ,GAAG,GAAG,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function normalizeProviderOutputUrl(value: string | null | undefined): string | undefined;
2
+ export declare function normalizePublicHttpUrl(value: string | null | undefined): string | undefined;
@@ -0,0 +1,50 @@
1
+ import { isPublicIpAddress } from "./safe-fetch.js";
2
+ const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/u;
3
+ // Normalizes a provider URL before it is exposed through metadata or streaming output.
4
+ // Нормализует URL провайдера перед публикацией в metadata или streaming output.
5
+ export function normalizeProviderOutputUrl(value) {
6
+ if (!value || CONTROL_CHARACTERS.test(value)) {
7
+ return undefined;
8
+ }
9
+ try {
10
+ const url = new URL(value);
11
+ if ((url.protocol !== "http:" && url.protocol !== "https:") ||
12
+ url.username !== "" ||
13
+ url.password !== "" ||
14
+ isLiteralLocalTarget(url.hostname)) {
15
+ return undefined;
16
+ }
17
+ return url.href;
18
+ }
19
+ catch {
20
+ return undefined;
21
+ }
22
+ }
23
+ // Backwards-compatible name for the provider output URL policy.
24
+ // Обратно совместимое имя политики provider output URL.
25
+ export function normalizePublicHttpUrl(value) {
26
+ return normalizeProviderOutputUrl(value);
27
+ }
28
+ function isLiteralLocalTarget(value) {
29
+ const hostname = value
30
+ .toLowerCase()
31
+ .replace(/^\[|\]$/g, "")
32
+ .replace(/\.$/, "");
33
+ if (hostname === "localhost" ||
34
+ hostname.endsWith(".localhost") ||
35
+ hostname === "0.0.0.0" ||
36
+ hostname === "::" ||
37
+ hostname === "::1") {
38
+ return true;
39
+ }
40
+ if (hostname.includes(":")) {
41
+ return !isPublicIpAddress(hostname);
42
+ }
43
+ const octets = hostname.split(".").map(Number);
44
+ if (octets.length !== 4 ||
45
+ octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) {
46
+ return false;
47
+ }
48
+ return !isPublicIpAddress(hostname);
49
+ }
50
+ //# sourceMappingURL=output-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-url.js","sourceRoot":"","sources":["../../src/shared/output-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AAEpD,uFAAuF;AACvF,gFAAgF;AAChF,MAAM,UAAU,0BAA0B,CAAC,KAAgC;IACzE,IAAI,CAAC,KAAK,IAAI,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAE3B,IACE,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;YACvD,GAAG,CAAC,QAAQ,KAAK,EAAE;YACnB,GAAG,CAAC,QAAQ,KAAK,EAAE;YACnB,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAClC,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,wDAAwD;AACxD,MAAM,UAAU,sBAAsB,CAAC,KAAgC;IACrE,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IACzC,MAAM,QAAQ,GAAG,KAAK;SACnB,WAAW,EAAE;SACb,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtB,IACE,QAAQ,KAAK,WAAW;QACxB,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC/B,QAAQ,KAAK,SAAS;QACtB,QAAQ,KAAK,IAAI;QACjB,QAAQ,KAAK,KAAK,EAClB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE/C,IACE,MAAM,CAAC,MAAM,KAAK,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC,EAC5E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface ProviderRateLimitGateOptions {
2
+ maxCooldownMs?: number;
3
+ now?: () => number;
4
+ }
5
+ export declare class ProviderRateLimitGate {
6
+ #private;
7
+ constructor(options?: ProviderRateLimitGateOptions);
8
+ defer(delayMs: number): void;
9
+ wait(signal?: AbortSignal): Promise<void>;
10
+ }
11
+ export declare function deferProviderRateLimitFromResponse(gate: ProviderRateLimitGate, response: Response, fallbackDelayMs?: number): void;
@@ -0,0 +1,52 @@
1
+ import { waitForAbortableDelay } from "./abort.js";
2
+ import { parseRetryAfterMs } from "./retry.js";
3
+ const DEFAULT_MAX_COOLDOWN_MS = 30_000;
4
+ const DEFAULT_RATE_LIMIT_FALLBACK_MS = 1_000;
5
+ // Shares an upstream rate-limit deadline between requests from one provider instance.
6
+ // Разделяет deadline upstream rate limit между запросами одного экземпляра provider.
7
+ export class ProviderRateLimitGate {
8
+ #maxCooldownMs;
9
+ #now;
10
+ #blockedUntil = 0;
11
+ constructor(options = {}) {
12
+ const maxCooldownMs = options.maxCooldownMs ?? DEFAULT_MAX_COOLDOWN_MS;
13
+ if (!Number.isFinite(maxCooldownMs) || maxCooldownMs < 0) {
14
+ throw new RangeError("Provider rate-limit maxCooldownMs must be a non-negative number.");
15
+ }
16
+ this.#maxCooldownMs = maxCooldownMs;
17
+ this.#now = options.now ?? Date.now;
18
+ }
19
+ // Extends the shared deadline without shortening an existing longer cooldown.
20
+ // Продлевает общий deadline, не сокращая уже установленный более длинный cooldown.
21
+ defer(delayMs) {
22
+ if (!Number.isFinite(delayMs) || delayMs <= 0 || this.#maxCooldownMs === 0) {
23
+ return;
24
+ }
25
+ const boundedDelayMs = Math.min(delayMs, this.#maxCooldownMs);
26
+ this.#blockedUntil = Math.max(this.#blockedUntil, this.#now() + boundedDelayMs);
27
+ }
28
+ // Waits for the current deadline and follows extensions announced while waiting.
29
+ // Ждет текущий deadline и учитывает продления, объявленные во время ожидания.
30
+ async wait(signal) {
31
+ while (true) {
32
+ const remainingMs = this.#blockedUntil - this.#now();
33
+ if (remainingMs <= 0) {
34
+ return;
35
+ }
36
+ await waitForAbortableDelay(remainingMs, signal);
37
+ }
38
+ }
39
+ }
40
+ // Records a server rate-limit hint for raw HTTP helpers that do not use fetchJson.
41
+ // Записывает server rate-limit hint для raw HTTP helpers, не использующих fetchJson.
42
+ export function deferProviderRateLimitFromResponse(gate, response, fallbackDelayMs = DEFAULT_RATE_LIMIT_FALLBACK_MS) {
43
+ const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
44
+ if (response.status === 429) {
45
+ gate.defer(retryAfterMs ?? fallbackDelayMs);
46
+ return;
47
+ }
48
+ if (response.status >= 500 && retryAfterMs !== undefined) {
49
+ gate.defer(retryAfterMs);
50
+ }
51
+ }
52
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/shared/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,uBAAuB,GAAG,MAAM,CAAC;AACvC,MAAM,8BAA8B,GAAG,KAAK,CAAC;AAO7C,sFAAsF;AACtF,qFAAqF;AACrF,MAAM,OAAO,qBAAqB;IACvB,cAAc,CAAS;IACvB,IAAI,CAAe;IAC5B,aAAa,GAAG,CAAC,CAAC;IAElB,YAAY,UAAwC,EAAE;QACpD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;QAEvE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,UAAU,CAAC,kEAAkE,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACtC,CAAC;IAED,8EAA8E;IAC9E,mFAAmF;IACnF,KAAK,CAAC,OAAe;QACnB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;YAC3E,OAAO;QACT,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,cAAc,CAAC,CAAC;IAClF,CAAC;IAED,iFAAiF;IACjF,8EAA8E;IAC9E,KAAK,CAAC,IAAI,CAAC,MAAoB;QAC7B,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAErD,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,MAAM,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;CACF;AAED,mFAAmF;AACnF,qFAAqF;AACrF,MAAM,UAAU,kCAAkC,CAChD,IAA2B,EAC3B,QAAkB,EAClB,eAAe,GAAG,8BAA8B;IAEhD,MAAM,YAAY,GAAG,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAE5E,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,eAAe,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface ReadBoundedResponseBodyOptions {
2
+ signal?: AbortSignal;
3
+ overflow?: "throw" | "truncate";
4
+ }
5
+ export declare function readBoundedResponseBytes(provider: string, response: Response, maxBytes: number, options?: ReadBoundedResponseBodyOptions): Promise<Uint8Array>;
6
+ export declare function readBoundedResponseText(provider: string, response: Response, maxBytes: number, options?: ReadBoundedResponseBodyOptions): Promise<string>;