tsarr 2.5.0 → 2.7.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 (137) hide show
  1. package/README.md +6 -3
  2. package/dist/cli/commands/config.d.ts.map +1 -1
  3. package/dist/cli/commands/doctor.d.ts.map +1 -1
  4. package/dist/cli/commands/qbit.d.ts +4 -0
  5. package/dist/cli/commands/qbit.d.ts.map +1 -0
  6. package/dist/cli/commands/seerr.d.ts +4 -0
  7. package/dist/cli/commands/seerr.d.ts.map +1 -0
  8. package/dist/cli/commands/service.d.ts +1 -2
  9. package/dist/cli/commands/service.d.ts.map +1 -1
  10. package/dist/cli/completions.d.ts.map +1 -1
  11. package/dist/cli/config.d.ts +6 -4
  12. package/dist/cli/config.d.ts.map +1 -1
  13. package/dist/cli/index.js +2709 -301
  14. package/dist/clients/bazarr.js +7 -7
  15. package/dist/clients/lidarr.js +7 -7
  16. package/dist/clients/prowlarr.js +7 -7
  17. package/dist/clients/qbittorrent-types.d.ts +2 -0
  18. package/dist/clients/qbittorrent-types.d.ts.map +1 -0
  19. package/dist/clients/qbittorrent.d.ts +40 -0
  20. package/dist/clients/qbittorrent.d.ts.map +1 -0
  21. package/dist/clients/qbittorrent.js +1011 -0
  22. package/dist/clients/radarr.js +7 -7
  23. package/dist/clients/readarr.js +7 -7
  24. package/dist/clients/seerr-types.d.ts +2 -0
  25. package/dist/clients/seerr-types.d.ts.map +1 -0
  26. package/dist/clients/seerr.d.ts +158 -0
  27. package/dist/clients/seerr.d.ts.map +1 -0
  28. package/dist/clients/seerr.js +1009 -0
  29. package/dist/clients/sonarr.js +7 -7
  30. package/dist/core/types.d.ts +6 -0
  31. package/dist/core/types.d.ts.map +1 -1
  32. package/dist/generated/bazarr/client/client.gen.d.ts.map +1 -1
  33. package/dist/generated/bazarr/client/types.gen.d.ts +1 -1
  34. package/dist/generated/bazarr/core/serverSentEvents.gen.d.ts +1 -1
  35. package/dist/generated/bazarr/core/serverSentEvents.gen.d.ts.map +1 -1
  36. package/dist/generated/bazarr/sdk.gen.d.ts +1 -1
  37. package/dist/generated/bazarr/sdk.gen.d.ts.map +1 -1
  38. package/dist/generated/lidarr/client/client.gen.d.ts.map +1 -1
  39. package/dist/generated/lidarr/client/types.gen.d.ts +1 -1
  40. package/dist/generated/lidarr/core/serverSentEvents.gen.d.ts +1 -1
  41. package/dist/generated/lidarr/core/serverSentEvents.gen.d.ts.map +1 -1
  42. package/dist/generated/lidarr/sdk.gen.d.ts +1 -1
  43. package/dist/generated/lidarr/sdk.gen.d.ts.map +1 -1
  44. package/dist/generated/prowlarr/client/client.gen.d.ts.map +1 -1
  45. package/dist/generated/prowlarr/client/types.gen.d.ts +1 -1
  46. package/dist/generated/prowlarr/core/serverSentEvents.gen.d.ts +1 -1
  47. package/dist/generated/prowlarr/core/serverSentEvents.gen.d.ts.map +1 -1
  48. package/dist/generated/prowlarr/sdk.gen.d.ts +1 -1
  49. package/dist/generated/prowlarr/sdk.gen.d.ts.map +1 -1
  50. package/dist/generated/qbittorrent/client/client.gen.d.ts +3 -0
  51. package/dist/generated/qbittorrent/client/client.gen.d.ts.map +1 -0
  52. package/dist/generated/qbittorrent/client/index.d.ts +9 -0
  53. package/dist/generated/qbittorrent/client/index.d.ts.map +1 -0
  54. package/dist/generated/qbittorrent/client/types.gen.d.ts +118 -0
  55. package/dist/generated/qbittorrent/client/types.gen.d.ts.map +1 -0
  56. package/dist/generated/qbittorrent/client/utils.gen.d.ts +34 -0
  57. package/dist/generated/qbittorrent/client/utils.gen.d.ts.map +1 -0
  58. package/dist/generated/qbittorrent/client.gen.d.ts +13 -0
  59. package/dist/generated/qbittorrent/client.gen.d.ts.map +1 -0
  60. package/dist/generated/qbittorrent/core/auth.gen.d.ts +19 -0
  61. package/dist/generated/qbittorrent/core/auth.gen.d.ts.map +1 -0
  62. package/dist/generated/qbittorrent/core/bodySerializer.gen.d.ts +26 -0
  63. package/dist/generated/qbittorrent/core/bodySerializer.gen.d.ts.map +1 -0
  64. package/dist/generated/qbittorrent/core/params.gen.d.ts +44 -0
  65. package/dist/generated/qbittorrent/core/params.gen.d.ts.map +1 -0
  66. package/dist/generated/qbittorrent/core/pathSerializer.gen.d.ts +34 -0
  67. package/dist/generated/qbittorrent/core/pathSerializer.gen.d.ts.map +1 -0
  68. package/dist/generated/qbittorrent/core/queryKeySerializer.gen.d.ts +19 -0
  69. package/dist/generated/qbittorrent/core/queryKeySerializer.gen.d.ts.map +1 -0
  70. package/dist/generated/qbittorrent/core/serverSentEvents.gen.d.ts +72 -0
  71. package/dist/generated/qbittorrent/core/serverSentEvents.gen.d.ts.map +1 -0
  72. package/dist/generated/qbittorrent/core/types.gen.d.ts +79 -0
  73. package/dist/generated/qbittorrent/core/types.gen.d.ts.map +1 -0
  74. package/dist/generated/qbittorrent/core/utils.gen.d.ts +20 -0
  75. package/dist/generated/qbittorrent/core/utils.gen.d.ts.map +1 -0
  76. package/dist/generated/qbittorrent/index.d.ts +3 -0
  77. package/dist/generated/qbittorrent/index.d.ts.map +1 -0
  78. package/dist/generated/qbittorrent/sdk.gen.d.ts +453 -0
  79. package/dist/generated/qbittorrent/sdk.gen.d.ts.map +1 -0
  80. package/dist/generated/qbittorrent/types.gen.d.ts +3689 -0
  81. package/dist/generated/qbittorrent/types.gen.d.ts.map +1 -0
  82. package/dist/generated/radarr/client/client.gen.d.ts.map +1 -1
  83. package/dist/generated/radarr/client/types.gen.d.ts +1 -1
  84. package/dist/generated/radarr/core/serverSentEvents.gen.d.ts +1 -1
  85. package/dist/generated/radarr/core/serverSentEvents.gen.d.ts.map +1 -1
  86. package/dist/generated/radarr/sdk.gen.d.ts +1 -1
  87. package/dist/generated/radarr/sdk.gen.d.ts.map +1 -1
  88. package/dist/generated/readarr/client/client.gen.d.ts.map +1 -1
  89. package/dist/generated/readarr/client/types.gen.d.ts +1 -1
  90. package/dist/generated/readarr/core/serverSentEvents.gen.d.ts +1 -1
  91. package/dist/generated/readarr/core/serverSentEvents.gen.d.ts.map +1 -1
  92. package/dist/generated/readarr/sdk.gen.d.ts +1 -1
  93. package/dist/generated/readarr/sdk.gen.d.ts.map +1 -1
  94. package/dist/generated/seerr/client/client.gen.d.ts +3 -0
  95. package/dist/generated/seerr/client/client.gen.d.ts.map +1 -0
  96. package/dist/generated/seerr/client/index.d.ts +9 -0
  97. package/dist/generated/seerr/client/index.d.ts.map +1 -0
  98. package/dist/generated/seerr/client/types.gen.d.ts +118 -0
  99. package/dist/generated/seerr/client/types.gen.d.ts.map +1 -0
  100. package/dist/generated/seerr/client/utils.gen.d.ts +34 -0
  101. package/dist/generated/seerr/client/utils.gen.d.ts.map +1 -0
  102. package/dist/generated/seerr/client.gen.d.ts +13 -0
  103. package/dist/generated/seerr/client.gen.d.ts.map +1 -0
  104. package/dist/generated/seerr/core/auth.gen.d.ts +19 -0
  105. package/dist/generated/seerr/core/auth.gen.d.ts.map +1 -0
  106. package/dist/generated/seerr/core/bodySerializer.gen.d.ts +26 -0
  107. package/dist/generated/seerr/core/bodySerializer.gen.d.ts.map +1 -0
  108. package/dist/generated/seerr/core/params.gen.d.ts +44 -0
  109. package/dist/generated/seerr/core/params.gen.d.ts.map +1 -0
  110. package/dist/generated/seerr/core/pathSerializer.gen.d.ts +34 -0
  111. package/dist/generated/seerr/core/pathSerializer.gen.d.ts.map +1 -0
  112. package/dist/generated/seerr/core/queryKeySerializer.gen.d.ts +19 -0
  113. package/dist/generated/seerr/core/queryKeySerializer.gen.d.ts.map +1 -0
  114. package/dist/generated/seerr/core/serverSentEvents.gen.d.ts +72 -0
  115. package/dist/generated/seerr/core/serverSentEvents.gen.d.ts.map +1 -0
  116. package/dist/generated/seerr/core/types.gen.d.ts +79 -0
  117. package/dist/generated/seerr/core/types.gen.d.ts.map +1 -0
  118. package/dist/generated/seerr/core/utils.gen.d.ts +20 -0
  119. package/dist/generated/seerr/core/utils.gen.d.ts.map +1 -0
  120. package/dist/generated/seerr/index.d.ts +3 -0
  121. package/dist/generated/seerr/index.d.ts.map +1 -0
  122. package/dist/generated/seerr/sdk.gen.d.ts +1309 -0
  123. package/dist/generated/seerr/sdk.gen.d.ts.map +1 -0
  124. package/dist/generated/seerr/types.gen.d.ts +4867 -0
  125. package/dist/generated/seerr/types.gen.d.ts.map +1 -0
  126. package/dist/generated/sonarr/client/client.gen.d.ts.map +1 -1
  127. package/dist/generated/sonarr/client/types.gen.d.ts +1 -1
  128. package/dist/generated/sonarr/core/serverSentEvents.gen.d.ts +1 -1
  129. package/dist/generated/sonarr/core/serverSentEvents.gen.d.ts.map +1 -1
  130. package/dist/generated/sonarr/sdk.gen.d.ts +1 -1
  131. package/dist/generated/sonarr/sdk.gen.d.ts.map +1 -1
  132. package/dist/index.d.ts +4 -0
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +41 -37
  135. package/dist/tsarr-2.7.0.tgz +0 -0
  136. package/package.json +26 -8
  137. package/dist/tsarr-2.5.0.tgz +0 -0
package/dist/cli/index.js CHANGED
@@ -75,6 +75,9 @@ function camelCase(str, opts) {
75
75
  function kebabCase(str, joiner) {
76
76
  return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => p.toLowerCase()).join(joiner ?? "-") : "";
77
77
  }
78
+ function snakeCase(str) {
79
+ return kebabCase(str || "", "_");
80
+ }
78
81
  var NUMBER_CHAR_RE, STR_SPLITTERS;
79
82
  var init_scule = __esm(() => {
80
83
  NUMBER_CHAR_RE = /\d/;
@@ -134,6 +137,15 @@ function parseRawArgs(args = [], opts = {}) {
134
137
  return "boolean";
135
138
  return "string";
136
139
  }
140
+ function isStringType(name) {
141
+ if (strings.has(name))
142
+ return true;
143
+ const aliases = mainToAliases.get(name) || [];
144
+ for (const alias of aliases)
145
+ if (strings.has(alias))
146
+ return true;
147
+ return false;
148
+ }
137
149
  const allOptions = new Set([
138
150
  ...booleans,
139
151
  ...strings,
@@ -181,8 +193,14 @@ function parseRawArgs(args = [], opts = {}) {
181
193
  }
182
194
  const out = { _: [] };
183
195
  out._ = parsed.positionals;
184
- for (const [key, value] of Object.entries(parsed.values))
185
- out[key] = value;
196
+ for (const [key, value] of Object.entries(parsed.values)) {
197
+ let coerced = value;
198
+ if (getType(key) === "boolean" && typeof value === "string")
199
+ coerced = value !== "false";
200
+ else if (isStringType(key) && typeof value === "boolean")
201
+ coerced = "";
202
+ out[key] = coerced;
203
+ }
186
204
  for (const [name] of Object.entries(negatedFlags)) {
187
205
  out[name] = false;
188
206
  const mainName = aliasToMain.get(name);
@@ -198,6 +216,8 @@ function parseRawArgs(args = [], opts = {}) {
198
216
  out[main] = out[alias];
199
217
  if (out[main] !== undefined && out[alias] === undefined)
200
218
  out[alias] = out[main];
219
+ if (out[alias] !== out[main] && defaults[main] === out[main])
220
+ out[main] = out[alias];
201
221
  }
202
222
  return out;
203
223
  }
@@ -265,6 +285,9 @@ function resolveArgs(argsDef) {
265
285
  });
266
286
  return args;
267
287
  }
288
+ async function resolvePlugins(plugins) {
289
+ return Promise.all(plugins.map((p) => resolveValue(p)));
290
+ }
268
291
  function defineCommand(def) {
269
292
  return def;
270
293
  }
@@ -277,42 +300,112 @@ async function runCommand(cmd, opts) {
277
300
  data: opts.data,
278
301
  cmd
279
302
  };
280
- if (typeof cmd.setup === "function")
281
- await cmd.setup(context);
303
+ const plugins = await resolvePlugins(cmd.plugins ?? []);
282
304
  let result;
305
+ let runError;
283
306
  try {
307
+ for (const plugin of plugins)
308
+ await plugin.setup?.(context);
309
+ if (typeof cmd.setup === "function")
310
+ await cmd.setup(context);
284
311
  const subCommands = await resolveValue(cmd.subCommands);
285
312
  if (subCommands && Object.keys(subCommands).length > 0) {
286
- const subCommandArgIndex = opts.rawArgs.findIndex((arg) => !arg.startsWith("-"));
287
- const subCommandName = opts.rawArgs[subCommandArgIndex];
288
- if (subCommandName) {
289
- if (!subCommands[subCommandName])
290
- throw new CLIError(`Unknown command ${cyan(subCommandName)}`, "E_UNKNOWN_COMMAND");
291
- const subCommand = await resolveValue(subCommands[subCommandName]);
292
- if (subCommand)
293
- await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });
294
- } else if (!cmd.run)
295
- throw new CLIError(`No command specified.`, "E_NO_COMMAND");
313
+ const subCommandArgIndex = findSubCommandIndex(opts.rawArgs, cmdArgs);
314
+ const explicitName = opts.rawArgs[subCommandArgIndex];
315
+ if (explicitName) {
316
+ const subCommand = await _findSubCommand(subCommands, explicitName);
317
+ if (!subCommand)
318
+ throw new CLIError(`Unknown command ${cyan(explicitName)}`, "E_UNKNOWN_COMMAND");
319
+ await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });
320
+ } else {
321
+ const defaultSubCommand = await resolveValue(cmd.default);
322
+ if (defaultSubCommand) {
323
+ if (cmd.run)
324
+ throw new CLIError(`Cannot specify both 'run' and 'default' on the same command.`, "E_DEFAULT_CONFLICT");
325
+ const subCommand = await _findSubCommand(subCommands, defaultSubCommand);
326
+ if (!subCommand)
327
+ throw new CLIError(`Default sub command ${cyan(defaultSubCommand)} not found in subCommands.`, "E_UNKNOWN_COMMAND");
328
+ await runCommand(subCommand, { rawArgs: opts.rawArgs });
329
+ } else if (!cmd.run)
330
+ throw new CLIError(`No command specified.`, "E_NO_COMMAND");
331
+ }
296
332
  }
297
333
  if (typeof cmd.run === "function")
298
334
  result = await cmd.run(context);
299
- } finally {
300
- if (typeof cmd.cleanup === "function")
301
- await cmd.cleanup(context);
335
+ } catch (error) {
336
+ runError = error;
302
337
  }
338
+ const cleanupErrors = [];
339
+ if (typeof cmd.cleanup === "function")
340
+ try {
341
+ await cmd.cleanup(context);
342
+ } catch (error) {
343
+ cleanupErrors.push(error);
344
+ }
345
+ for (const plugin of [...plugins].reverse())
346
+ try {
347
+ await plugin.cleanup?.(context);
348
+ } catch (error) {
349
+ cleanupErrors.push(error);
350
+ }
351
+ if (runError)
352
+ throw runError;
353
+ if (cleanupErrors.length === 1)
354
+ throw cleanupErrors[0];
355
+ if (cleanupErrors.length > 1)
356
+ throw new Error("Multiple cleanup errors", { cause: cleanupErrors });
303
357
  return { result };
304
358
  }
305
359
  async function resolveSubCommand(cmd, rawArgs, parent) {
306
360
  const subCommands = await resolveValue(cmd.subCommands);
307
361
  if (subCommands && Object.keys(subCommands).length > 0) {
308
- const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-"));
362
+ const subCommandArgIndex = findSubCommandIndex(rawArgs, await resolveValue(cmd.args || {}));
309
363
  const subCommandName = rawArgs[subCommandArgIndex];
310
- const subCommand = await resolveValue(subCommands[subCommandName]);
364
+ const subCommand = await _findSubCommand(subCommands, subCommandName);
311
365
  if (subCommand)
312
366
  return resolveSubCommand(subCommand, rawArgs.slice(subCommandArgIndex + 1), cmd);
313
367
  }
314
368
  return [cmd, parent];
315
369
  }
370
+ async function _findSubCommand(subCommands, name) {
371
+ if (name in subCommands)
372
+ return resolveValue(subCommands[name]);
373
+ for (const sub of Object.values(subCommands)) {
374
+ const resolved = await resolveValue(sub);
375
+ const meta = await resolveValue(resolved?.meta);
376
+ if (meta?.alias) {
377
+ if (toArray(meta.alias).includes(name))
378
+ return resolved;
379
+ }
380
+ }
381
+ }
382
+ function findSubCommandIndex(rawArgs, argsDef) {
383
+ for (let i = 0;i < rawArgs.length; i++) {
384
+ const arg = rawArgs[i];
385
+ if (arg === "--")
386
+ return -1;
387
+ if (arg.startsWith("-")) {
388
+ if (!arg.includes("=") && _isValueFlag(arg, argsDef))
389
+ i++;
390
+ continue;
391
+ }
392
+ return i;
393
+ }
394
+ return -1;
395
+ }
396
+ function _isValueFlag(flag, argsDef) {
397
+ const name = flag.replace(/^-{1,2}/, "");
398
+ const normalized = camelCase(name);
399
+ for (const [key, def] of Object.entries(argsDef)) {
400
+ if (def.type !== "string" && def.type !== "enum")
401
+ continue;
402
+ if (normalized === camelCase(key))
403
+ return true;
404
+ if ((Array.isArray(def.alias) ? def.alias : def.alias ? [def.alias] : []).includes(name))
405
+ return true;
406
+ }
407
+ return false;
408
+ }
316
409
  async function showUsage(cmd, parent) {
317
410
  try {
318
411
  console.log(await renderUsage(cmd, parent) + `
@@ -334,23 +427,18 @@ async function renderUsage(cmd, parent) {
334
427
  if (arg.type === "positional") {
335
428
  const name = arg.name.toUpperCase();
336
429
  const isRequired = arg.required !== false && arg.default === undefined;
337
- const defaultHint = arg.default ? `="${arg.default}"` : "";
338
- posLines.push([
339
- cyan(name + defaultHint),
340
- arg.description || "",
341
- arg.valueHint ? `<${arg.valueHint}>` : ""
342
- ]);
430
+ posLines.push([cyan(name + renderValueHint(arg)), renderDescription(arg, isRequired)]);
343
431
  usageLine.push(isRequired ? `<${name}>` : `[${name}]`);
344
432
  } else {
345
433
  const isRequired = arg.required === true && arg.default === undefined;
346
- const argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(", ") + (arg.type === "string" && (arg.valueHint || arg.default) ? `=${arg.valueHint ? `<${arg.valueHint}>` : `"${arg.default || ""}"`}` : "") + (arg.type === "enum" && arg.options ? `=<${arg.options.join("|")}>` : "");
347
- argLines.push([cyan(argStr + (isRequired ? " (required)" : "")), arg.description || ""]);
434
+ const argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(", ") + renderValueHint(arg);
435
+ argLines.push([cyan(argStr), renderDescription(arg, isRequired)]);
348
436
  if (arg.type === "boolean" && (arg.default === true || arg.negativeDescription) && !negativePrefixRe.test(arg.name)) {
349
437
  const negativeArgStr = [...(arg.alias || []).map((a) => `--no-${a}`), `--no-${arg.name}`].join(", ");
350
- argLines.push([cyan(negativeArgStr + (isRequired ? " (required)" : "")), arg.negativeDescription || ""]);
438
+ argLines.push([cyan(negativeArgStr), [arg.negativeDescription, isRequired ? gray("(Required)") : ""].filter(Boolean).join(" ")]);
351
439
  }
352
440
  if (isRequired)
353
- usageLine.push(argStr);
441
+ usageLine.push(`--${arg.name}` + renderValueHint(arg));
354
442
  }
355
443
  if (cmd.subCommands) {
356
444
  const commandNames = [];
@@ -359,8 +447,10 @@ async function renderUsage(cmd, parent) {
359
447
  const meta = await resolveValue((await resolveValue(sub))?.meta);
360
448
  if (meta?.hidden)
361
449
  continue;
362
- commandsLines.push([cyan(name), meta?.description || ""]);
363
- commandNames.push(name);
450
+ const aliases = toArray(meta?.alias);
451
+ const label = [name, ...aliases].join(", ");
452
+ commandsLines.push([cyan(label), meta?.description || ""]);
453
+ commandNames.push(name, ...aliases);
364
454
  }
365
455
  usageLine.push(commandNames.join("|"));
366
456
  }
@@ -387,14 +477,33 @@ async function renderUsage(cmd, parent) {
387
477
  return usageLines.filter((l) => typeof l === "string").join(`
388
478
  `);
389
479
  }
480
+ function renderValueHint(arg) {
481
+ const valueHint = arg.valueHint ? `=<${arg.valueHint}>` : "";
482
+ const fallbackValueHint = valueHint || `=<${snakeCase(arg.name)}>`;
483
+ if (!arg.type || arg.type === "positional" || arg.type === "boolean")
484
+ return valueHint;
485
+ if (arg.type === "enum" && arg.options?.length)
486
+ return `=<${arg.options.join("|")}>`;
487
+ return fallbackValueHint;
488
+ }
489
+ function renderDescription(arg, required) {
490
+ const requiredHint = required ? gray("(Required)") : "";
491
+ const defaultHint = arg.default === undefined ? "" : gray(`(Default: ${arg.default})`);
492
+ return [
493
+ arg.description,
494
+ requiredHint,
495
+ defaultHint
496
+ ].filter(Boolean).join(" ");
497
+ }
390
498
  async function runMain(cmd, opts = {}) {
391
499
  const rawArgs = opts.rawArgs || process.argv.slice(2);
392
500
  const showUsage$1 = opts.showUsage || showUsage;
393
501
  try {
394
- if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
502
+ const builtinFlags = await _resolveBuiltinFlags(cmd);
503
+ if (builtinFlags.help.length > 0 && rawArgs.some((arg) => builtinFlags.help.includes(arg))) {
395
504
  await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
396
505
  process.exit(0);
397
- } else if (rawArgs.length === 1 && rawArgs[0] === "--version") {
506
+ } else if (rawArgs.length === 1 && builtinFlags.version.includes(rawArgs[0])) {
398
507
  const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta;
399
508
  if (!meta?.version)
400
509
  throw new CLIError("No version specified", "E_NO_VERSION");
@@ -411,6 +520,27 @@ async function runMain(cmd, opts = {}) {
411
520
  process.exit(1);
412
521
  }
413
522
  }
523
+ async function _resolveBuiltinFlags(cmd) {
524
+ const argsDef = await resolveValue(cmd.args || {});
525
+ const userNames = /* @__PURE__ */ new Set;
526
+ const userAliases = /* @__PURE__ */ new Set;
527
+ for (const [name, def] of Object.entries(argsDef)) {
528
+ userNames.add(name);
529
+ for (const alias of toArray(def.alias))
530
+ userAliases.add(alias);
531
+ }
532
+ return {
533
+ help: _getBuiltinFlags("help", "h", userNames, userAliases),
534
+ version: _getBuiltinFlags("version", "v", userNames, userAliases)
535
+ };
536
+ }
537
+ function _getBuiltinFlags(long, short, userNames, userAliases) {
538
+ if (userNames.has(long) || userAliases.has(long))
539
+ return [];
540
+ if (userNames.has(short) || userAliases.has(short))
541
+ return [`--${long}`];
542
+ return [`--${long}`, `-${short}`];
543
+ }
414
544
  var CLIError, noColor, _c = (c, r = 39) => (t) => noColor ? t : `\x1B[${c}m${t}\x1B[${r}m`, bold, cyan, gray, underline, negativePrefixRe;
415
545
  var init_dist = __esm(() => {
416
546
  init_scule();
@@ -503,7 +633,7 @@ var init_bodySerializer_gen = __esm(() => {
503
633
  });
504
634
 
505
635
  // src/generated/radarr/core/serverSentEvents.gen.ts
506
- var createSseClient = ({
636
+ function createSseClient({
507
637
  onRequest,
508
638
  onSseError,
509
639
  onSseEvent,
@@ -515,7 +645,7 @@ var createSseClient = ({
515
645
  sseSleepFn,
516
646
  url,
517
647
  ...options
518
- }) => {
648
+ }) {
519
649
  let lastEventId;
520
650
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
521
651
  const createStream = async function* () {
@@ -562,8 +692,7 @@ var createSseClient = ({
562
692
  if (done)
563
693
  break;
564
694
  buffer += value;
565
- buffer = buffer.replace(/\r\n/g, `
566
- `).replace(/\r/g, `
695
+ buffer = buffer.replace(/\r\n?/g, `
567
696
  `);
568
697
  const chunks = buffer.split(`
569
698
 
@@ -636,7 +765,7 @@ var createSseClient = ({
636
765
  };
637
766
  const stream = createStream();
638
767
  return { stream };
639
- };
768
+ }
640
769
 
641
770
  // src/generated/radarr/core/pathSerializer.gen.ts
642
771
  var separatorArrayExplode = (style) => {
@@ -1101,8 +1230,9 @@ var createClient = (config = {}) => {
1101
1230
  if (opts.body === undefined || opts.serializedBody === "") {
1102
1231
  opts.headers.delete("Content-Type");
1103
1232
  }
1104
- const url = buildUrl(opts);
1105
- return { opts, url };
1233
+ const resolvedOpts = opts;
1234
+ const url = buildUrl(resolvedOpts);
1235
+ return { opts: resolvedOpts, url };
1106
1236
  };
1107
1237
  const request = async (options) => {
1108
1238
  const { opts, url } = await beforeRequest(options);
@@ -4732,7 +4862,9 @@ function normalizeServiceConfig(service) {
4732
4862
  const normalized = {
4733
4863
  baseUrl: service.baseUrl ?? "",
4734
4864
  apiKey: service.apiKey ?? "",
4735
- ...service.apiKeyFile ? { apiKeyFile: service.apiKeyFile } : {}
4865
+ ...service.apiKeyFile ? { apiKeyFile: service.apiKeyFile } : {},
4866
+ ...service.username ? { username: service.username } : {},
4867
+ ...service.password ? { password: service.password } : {}
4736
4868
  };
4737
4869
  const timeout = typeof service.timeout === "string" ? Number(service.timeout) : service.timeout;
4738
4870
  if (typeof timeout === "number" && Number.isFinite(timeout)) {
@@ -4761,13 +4893,22 @@ function getEnvConfig() {
4761
4893
  for (const service of SERVICES) {
4762
4894
  const upper = service.toUpperCase();
4763
4895
  const baseUrl = process.env[`TSARR_${upper}_URL`];
4764
- const apiKey = process.env[`TSARR_${upper}_API_KEY`];
4765
4896
  const timeout = process.env[`TSARR_${upper}_TIMEOUT`];
4766
4897
  const partial = {};
4767
4898
  if (baseUrl)
4768
4899
  partial.baseUrl = baseUrl;
4769
- if (apiKey)
4770
- partial.apiKey = apiKey;
4900
+ if (service === "qbittorrent") {
4901
+ const username = process.env.TSARR_QBITTORRENT_USERNAME;
4902
+ const password = process.env.TSARR_QBITTORRENT_PASSWORD;
4903
+ if (username)
4904
+ partial.username = username;
4905
+ if (password)
4906
+ partial.password = password;
4907
+ } else {
4908
+ const apiKey = process.env[`TSARR_${upper}_API_KEY`];
4909
+ if (apiKey)
4910
+ partial.apiKey = apiKey;
4911
+ }
4771
4912
  if (timeout)
4772
4913
  partial.timeout = Number(timeout);
4773
4914
  if (Object.keys(partial).length > 0) {
@@ -4850,6 +4991,16 @@ function getServiceConfig(serviceName) {
4850
4991
  const service = config.services[serviceName];
4851
4992
  if (!service?.baseUrl)
4852
4993
  return null;
4994
+ if (serviceName === "qbittorrent") {
4995
+ if (!service.username || !service.password)
4996
+ return null;
4997
+ return {
4998
+ baseUrl: service.baseUrl,
4999
+ username: service.username,
5000
+ password: service.password,
5001
+ ...service.timeout ? { timeout: service.timeout } : {}
5002
+ };
5003
+ }
4853
5004
  let apiKey = service.apiKey;
4854
5005
  const apiKeyFilePath = getResolvedApiKeyFilePath(serviceName, service, localPath, local, global);
4855
5006
  if (!apiKey && apiKeyFilePath) {
@@ -4922,7 +5073,16 @@ function loadScopedConfig(scope) {
4922
5073
  }
4923
5074
  var SERVICES, GLOBAL_CONFIG_DIR, GLOBAL_CONFIG_PATH, LOCAL_CONFIG_NAME = ".tsarr.json";
4924
5075
  var init_config = __esm(() => {
4925
- SERVICES = ["radarr", "sonarr", "lidarr", "readarr", "prowlarr", "bazarr"];
5076
+ SERVICES = [
5077
+ "radarr",
5078
+ "sonarr",
5079
+ "lidarr",
5080
+ "readarr",
5081
+ "prowlarr",
5082
+ "bazarr",
5083
+ "qbittorrent",
5084
+ "seerr"
5085
+ ];
4926
5086
  GLOBAL_CONFIG_DIR = join(homedir(), ".config", "tsarr");
4927
5087
  GLOBAL_CONFIG_PATH = join(GLOBAL_CONFIG_DIR, "config.json");
4928
5088
  });
@@ -5199,7 +5359,8 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
5199
5359
  async run({ args }) {
5200
5360
  const config = getServiceConfig(serviceName);
5201
5361
  if (!config) {
5202
- consola.error(`${serviceName} is not configured. Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_URL and TSARR_${serviceName.toUpperCase()}_API_KEY environment variables.`);
5362
+ const envHint = serviceName === "qbittorrent" ? `TSARR_QBITTORRENT_URL, TSARR_QBITTORRENT_USERNAME, and TSARR_QBITTORRENT_PASSWORD` : `TSARR_${serviceName.toUpperCase()}_URL and TSARR_${serviceName.toUpperCase()}_API_KEY`;
5363
+ consola.error(`${serviceName} is not configured. Run \`tsarr config init\` or set ${envHint} environment variables.`);
5203
5364
  process.exit(1);
5204
5365
  }
5205
5366
  try {
@@ -5241,8 +5402,9 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
5241
5402
  const err = raw.error;
5242
5403
  const status = err?.status ?? raw?.response?.status;
5243
5404
  if (status === 401) {
5244
- consola.error(`Unauthorized. Check your API key.
5245
- Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY`);
5405
+ const authHint = serviceName === "qbittorrent" ? "Check your username and password." : `Check your API key.
5406
+ Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY`;
5407
+ consola.error(`Unauthorized. ${authHint}`);
5246
5408
  } else if (status === 404) {
5247
5409
  consola.error("Not found.");
5248
5410
  } else {
@@ -5304,6 +5466,8 @@ function isWriteAction(actionName) {
5304
5466
  "create",
5305
5467
  "delete",
5306
5468
  "edit",
5469
+ "pause",
5470
+ "resume",
5307
5471
  "refresh",
5308
5472
  "manual-search",
5309
5473
  "grab",
@@ -5991,7 +6155,7 @@ var init_bodySerializer_gen2 = __esm(() => {
5991
6155
  });
5992
6156
 
5993
6157
  // src/generated/sonarr/core/serverSentEvents.gen.ts
5994
- var createSseClient2 = ({
6158
+ function createSseClient2({
5995
6159
  onRequest,
5996
6160
  onSseError,
5997
6161
  onSseEvent,
@@ -6003,7 +6167,7 @@ var createSseClient2 = ({
6003
6167
  sseSleepFn,
6004
6168
  url,
6005
6169
  ...options
6006
- }) => {
6170
+ }) {
6007
6171
  let lastEventId;
6008
6172
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
6009
6173
  const createStream = async function* () {
@@ -6050,8 +6214,7 @@ var createSseClient2 = ({
6050
6214
  if (done)
6051
6215
  break;
6052
6216
  buffer += value;
6053
- buffer = buffer.replace(/\r\n/g, `
6054
- `).replace(/\r/g, `
6217
+ buffer = buffer.replace(/\r\n?/g, `
6055
6218
  `);
6056
6219
  const chunks = buffer.split(`
6057
6220
 
@@ -6124,7 +6287,7 @@ var createSseClient2 = ({
6124
6287
  };
6125
6288
  const stream = createStream();
6126
6289
  return { stream };
6127
- };
6290
+ }
6128
6291
 
6129
6292
  // src/generated/sonarr/core/pathSerializer.gen.ts
6130
6293
  var separatorArrayExplode2 = (style) => {
@@ -6589,8 +6752,9 @@ var createClient2 = (config = {}) => {
6589
6752
  if (opts.body === undefined || opts.serializedBody === "") {
6590
6753
  opts.headers.delete("Content-Type");
6591
6754
  }
6592
- const url = buildUrl2(opts);
6593
- return { opts, url };
6755
+ const resolvedOpts = opts;
6756
+ const url = buildUrl2(resolvedOpts);
6757
+ return { opts: resolvedOpts, url };
6594
6758
  };
6595
6759
  const request = async (options) => {
6596
6760
  const { opts, url } = await beforeRequest(options);
@@ -9166,7 +9330,7 @@ var init_bodySerializer_gen3 = __esm(() => {
9166
9330
  });
9167
9331
 
9168
9332
  // src/generated/lidarr/core/serverSentEvents.gen.ts
9169
- var createSseClient3 = ({
9333
+ function createSseClient3({
9170
9334
  onRequest,
9171
9335
  onSseError,
9172
9336
  onSseEvent,
@@ -9178,7 +9342,7 @@ var createSseClient3 = ({
9178
9342
  sseSleepFn,
9179
9343
  url,
9180
9344
  ...options
9181
- }) => {
9345
+ }) {
9182
9346
  let lastEventId;
9183
9347
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
9184
9348
  const createStream = async function* () {
@@ -9225,8 +9389,7 @@ var createSseClient3 = ({
9225
9389
  if (done)
9226
9390
  break;
9227
9391
  buffer += value;
9228
- buffer = buffer.replace(/\r\n/g, `
9229
- `).replace(/\r/g, `
9392
+ buffer = buffer.replace(/\r\n?/g, `
9230
9393
  `);
9231
9394
  const chunks = buffer.split(`
9232
9395
 
@@ -9299,7 +9462,7 @@ var createSseClient3 = ({
9299
9462
  };
9300
9463
  const stream = createStream();
9301
9464
  return { stream };
9302
- };
9465
+ }
9303
9466
 
9304
9467
  // src/generated/lidarr/core/pathSerializer.gen.ts
9305
9468
  var separatorArrayExplode3 = (style) => {
@@ -9764,8 +9927,9 @@ var createClient3 = (config = {}) => {
9764
9927
  if (opts.body === undefined || opts.serializedBody === "") {
9765
9928
  opts.headers.delete("Content-Type");
9766
9929
  }
9767
- const url = buildUrl3(opts);
9768
- return { opts, url };
9930
+ const resolvedOpts = opts;
9931
+ const url = buildUrl3(resolvedOpts);
9932
+ return { opts: resolvedOpts, url };
9769
9933
  };
9770
9934
  const request = async (options) => {
9771
9935
  const { opts, url } = await beforeRequest(options);
@@ -12220,7 +12384,7 @@ var init_bodySerializer_gen4 = __esm(() => {
12220
12384
  });
12221
12385
 
12222
12386
  // src/generated/readarr/core/serverSentEvents.gen.ts
12223
- var createSseClient4 = ({
12387
+ function createSseClient4({
12224
12388
  onRequest,
12225
12389
  onSseError,
12226
12390
  onSseEvent,
@@ -12232,7 +12396,7 @@ var createSseClient4 = ({
12232
12396
  sseSleepFn,
12233
12397
  url,
12234
12398
  ...options
12235
- }) => {
12399
+ }) {
12236
12400
  let lastEventId;
12237
12401
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
12238
12402
  const createStream = async function* () {
@@ -12279,8 +12443,7 @@ var createSseClient4 = ({
12279
12443
  if (done)
12280
12444
  break;
12281
12445
  buffer += value;
12282
- buffer = buffer.replace(/\r\n/g, `
12283
- `).replace(/\r/g, `
12446
+ buffer = buffer.replace(/\r\n?/g, `
12284
12447
  `);
12285
12448
  const chunks = buffer.split(`
12286
12449
 
@@ -12353,7 +12516,7 @@ var createSseClient4 = ({
12353
12516
  };
12354
12517
  const stream = createStream();
12355
12518
  return { stream };
12356
- };
12519
+ }
12357
12520
 
12358
12521
  // src/generated/readarr/core/pathSerializer.gen.ts
12359
12522
  var separatorArrayExplode4 = (style) => {
@@ -12818,8 +12981,9 @@ var createClient4 = (config = {}) => {
12818
12981
  if (opts.body === undefined || opts.serializedBody === "") {
12819
12982
  opts.headers.delete("Content-Type");
12820
12983
  }
12821
- const url = buildUrl4(opts);
12822
- return { opts, url };
12984
+ const resolvedOpts = opts;
12985
+ const url = buildUrl4(resolvedOpts);
12986
+ return { opts: resolvedOpts, url };
12823
12987
  };
12824
12988
  const request = async (options) => {
12825
12989
  const { opts, url } = await beforeRequest(options);
@@ -15255,7 +15419,7 @@ var init_bodySerializer_gen5 = __esm(() => {
15255
15419
  });
15256
15420
 
15257
15421
  // src/generated/prowlarr/core/serverSentEvents.gen.ts
15258
- var createSseClient5 = ({
15422
+ function createSseClient5({
15259
15423
  onRequest,
15260
15424
  onSseError,
15261
15425
  onSseEvent,
@@ -15267,7 +15431,7 @@ var createSseClient5 = ({
15267
15431
  sseSleepFn,
15268
15432
  url,
15269
15433
  ...options
15270
- }) => {
15434
+ }) {
15271
15435
  let lastEventId;
15272
15436
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
15273
15437
  const createStream = async function* () {
@@ -15314,8 +15478,7 @@ var createSseClient5 = ({
15314
15478
  if (done)
15315
15479
  break;
15316
15480
  buffer += value;
15317
- buffer = buffer.replace(/\r\n/g, `
15318
- `).replace(/\r/g, `
15481
+ buffer = buffer.replace(/\r\n?/g, `
15319
15482
  `);
15320
15483
  const chunks = buffer.split(`
15321
15484
 
@@ -15388,7 +15551,7 @@ var createSseClient5 = ({
15388
15551
  };
15389
15552
  const stream = createStream();
15390
15553
  return { stream };
15391
- };
15554
+ }
15392
15555
 
15393
15556
  // src/generated/prowlarr/core/pathSerializer.gen.ts
15394
15557
  var separatorArrayExplode5 = (style) => {
@@ -15853,8 +16016,9 @@ var createClient5 = (config = {}) => {
15853
16016
  if (opts.body === undefined || opts.serializedBody === "") {
15854
16017
  opts.headers.delete("Content-Type");
15855
16018
  }
15856
- const url = buildUrl5(opts);
15857
- return { opts, url };
16019
+ const resolvedOpts = opts;
16020
+ const url = buildUrl5(resolvedOpts);
16021
+ return { opts: resolvedOpts, url };
15858
16022
  };
15859
16023
  const request = async (options) => {
15860
16024
  const { opts, url } = await beforeRequest(options);
@@ -17254,7 +17418,7 @@ var init_bodySerializer_gen6 = __esm(() => {
17254
17418
  });
17255
17419
 
17256
17420
  // src/generated/bazarr/core/serverSentEvents.gen.ts
17257
- var createSseClient6 = ({
17421
+ function createSseClient6({
17258
17422
  onRequest,
17259
17423
  onSseError,
17260
17424
  onSseEvent,
@@ -17266,7 +17430,7 @@ var createSseClient6 = ({
17266
17430
  sseSleepFn,
17267
17431
  url,
17268
17432
  ...options
17269
- }) => {
17433
+ }) {
17270
17434
  let lastEventId;
17271
17435
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
17272
17436
  const createStream = async function* () {
@@ -17313,8 +17477,7 @@ var createSseClient6 = ({
17313
17477
  if (done)
17314
17478
  break;
17315
17479
  buffer += value;
17316
- buffer = buffer.replace(/\r\n/g, `
17317
- `).replace(/\r/g, `
17480
+ buffer = buffer.replace(/\r\n?/g, `
17318
17481
  `);
17319
17482
  const chunks = buffer.split(`
17320
17483
 
@@ -17387,7 +17550,7 @@ var createSseClient6 = ({
17387
17550
  };
17388
17551
  const stream = createStream();
17389
17552
  return { stream };
17390
- };
17553
+ }
17391
17554
 
17392
17555
  // src/generated/bazarr/core/pathSerializer.gen.ts
17393
17556
  var separatorArrayExplode6 = (style) => {
@@ -17852,8 +18015,9 @@ var createClient6 = (config = {}) => {
17852
18015
  if (opts.body === undefined || opts.serializedBody === "") {
17853
18016
  opts.headers.delete("Content-Type");
17854
18017
  }
17855
- const url = buildUrl6(opts);
17856
- return { opts, url };
18018
+ const resolvedOpts = opts;
18019
+ const url = buildUrl6(resolvedOpts);
18020
+ return { opts: resolvedOpts, url };
17857
18021
  };
17858
18022
  const request = async (options) => {
17859
18023
  const { opts, url } = await beforeRequest(options);
@@ -18794,191 +18958,2392 @@ var init_bazarr3 = __esm(() => {
18794
18958
  bazarr = buildServiceCommand("bazarr", "Manage Bazarr (Subtitles)", (config) => new BazarrClient(config), resources6);
18795
18959
  });
18796
18960
 
18797
- // src/cli/commands/doctor.ts
18798
- var exports_doctor = {};
18799
- __export(exports_doctor, {
18800
- doctor: () => doctor
18801
- });
18802
- function classifyError(error) {
18803
- if (!(error instanceof Error))
18804
- return "Unknown error";
18805
- const msg = error.message;
18806
- const cause = error.cause;
18807
- if (cause?.code === "ECONNREFUSED" || msg.includes("ECONNREFUSED")) {
18808
- return "Connection refused - is the service running?";
18809
- }
18810
- if (cause?.code === "ENOTFOUND" || msg.includes("ENOTFOUND")) {
18811
- return "Host not found - check the URL";
18812
- }
18813
- if (cause?.code === "ECONNRESET" || msg.includes("ECONNRESET")) {
18814
- return "Connection reset - service may have crashed";
18815
- }
18816
- if (cause?.code === "ETIMEDOUT" || msg.includes("ETIMEDOUT") || msg.includes("timed out")) {
18817
- return "Connection timed out - service may be unreachable";
18818
- }
18819
- if (msg.includes("fetch failed") || msg.includes("Failed to fetch")) {
18820
- return `Service unreachable - ${cause?.message ?? "check URL and network"}`;
18821
- }
18822
- if (msg.includes("401") || msg.includes("Unauthorized")) {
18823
- return "Authentication failed (401) - check your API key";
18824
- }
18825
- if (msg.includes("403") || msg.includes("Forbidden")) {
18826
- return "Access denied (403) - check your API key permissions";
18827
- }
18828
- if (msg.includes("502") || msg.includes("Bad Gateway")) {
18829
- return "Bad gateway (502) - reverse proxy or service issue";
18830
- }
18831
- if (msg.includes("503") || msg.includes("Service Unavailable")) {
18832
- return "Service unavailable (503) - service may be starting up";
18833
- }
18834
- if (msg.includes("CERT") || msg.includes("certificate") || msg.includes("SSL")) {
18835
- return "SSL/TLS certificate error - check HTTPS configuration";
18836
- }
18837
- return msg;
18838
- }
18839
- function extractVersion(service, status) {
18840
- const data = status?.data ?? status;
18841
- if (typeof data === "string") {
18842
- return null;
18843
- }
18844
- if (service === "bazarr") {
18845
- return data?.data?.bazarr_version ?? data?.bazarr_version ?? null;
18961
+ // src/generated/qbittorrent/core/bodySerializer.gen.ts
18962
+ var serializeUrlSearchParamsPair = (data, key, value) => {
18963
+ if (typeof value === "string") {
18964
+ data.append(key, value);
18965
+ } else {
18966
+ data.append(key, JSON.stringify(value));
18846
18967
  }
18847
- return data?.version ?? status?.version ?? null;
18848
- }
18849
- var clientFactories, doctor;
18850
- var init_doctor = __esm(() => {
18851
- init_dist();
18852
- init_dist2();
18853
- init_bazarr2();
18854
- init_lidarr2();
18855
- init_prowlarr2();
18856
- init_radarr2();
18857
- init_readarr2();
18858
- init_sonarr2();
18859
- init_config();
18860
- init_output();
18861
- clientFactories = {
18862
- radarr: (c3) => new RadarrClient(c3),
18863
- sonarr: (c3) => new SonarrClient(c3),
18864
- lidarr: (c3) => new LidarrClient(c3),
18865
- readarr: (c3) => new ReadarrClient(c3),
18866
- prowlarr: (c3) => new ProwlarrClient(c3),
18867
- bazarr: (c3) => new BazarrClient(c3)
18968
+ }, jsonBodySerializer7, urlSearchParamsBodySerializer2;
18969
+ var init_bodySerializer_gen7 = __esm(() => {
18970
+ jsonBodySerializer7 = {
18971
+ bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
18868
18972
  };
18869
- doctor = defineCommand({
18870
- meta: {
18871
- name: "doctor",
18872
- description: "Test all configured service connections"
18873
- },
18874
- args: {
18875
- json: { type: "boolean", description: "Output as JSON" },
18876
- table: { type: "boolean", description: "Output as table" },
18877
- plain: { type: "boolean", description: "Output as TSV (no colors, for piping)" },
18878
- quiet: { type: "boolean", alias: "q", description: "Output service names only" },
18879
- select: { type: "string", description: "Cherry-pick fields (comma-separated, JSON mode)" }
18880
- },
18881
- async run({ args }) {
18882
- const format = detectFormat(args);
18883
- let hasAny = false;
18884
- const results = [];
18885
- if (format === "table") {
18886
- consola.info(`Checking connections...
18887
- `);
18888
- }
18889
- for (const service of SERVICES) {
18890
- const svcConfig = getServiceConfig(service);
18891
- if (!svcConfig) {
18892
- results.push({
18893
- service,
18894
- configured: false,
18895
- status: "not configured"
18896
- });
18897
- continue;
18973
+ urlSearchParamsBodySerializer2 = {
18974
+ bodySerializer: (body) => {
18975
+ const data = new URLSearchParams;
18976
+ Object.entries(body).forEach(([key, value]) => {
18977
+ if (value === undefined || value === null) {
18978
+ return;
18898
18979
  }
18899
- hasAny = true;
18900
- try {
18901
- const factory = clientFactories[service];
18902
- if (!factory) {
18903
- results.push({
18904
- service,
18905
- configured: true,
18906
- status: "fail",
18907
- baseUrl: svcConfig.baseUrl,
18908
- error: "No client factory available"
18909
- });
18910
- continue;
18911
- }
18912
- const client7 = factory(svcConfig);
18913
- const status = await client7.getSystemStatus();
18914
- const version = extractVersion(service, status) ?? "?";
18915
- if (version === "?") {
18916
- throw new Error("Unexpected response payload");
18917
- }
18918
- results.push({
18919
- service,
18920
- configured: true,
18921
- status: "ok",
18922
- version: String(version),
18923
- baseUrl: svcConfig.baseUrl
18924
- });
18925
- } catch (error) {
18926
- results.push({
18927
- service,
18928
- configured: true,
18929
- status: "fail",
18930
- baseUrl: svcConfig.baseUrl,
18931
- error: classifyError(error)
18932
- });
18980
+ if (Array.isArray(value)) {
18981
+ value.forEach((v2) => serializeUrlSearchParamsPair(data, key, v2));
18982
+ } else {
18983
+ serializeUrlSearchParamsPair(data, key, value);
18933
18984
  }
18934
- }
18935
- const hadFailure = !hasAny || results.some((r3) => r3.status === "fail");
18936
- if (!hasAny && format === "table") {
18937
- consola.warn("\nNo services configured. Run `tsarr config init` to set up.");
18938
- }
18939
- formatOutput(results, {
18940
- format,
18941
- columns: ["service", "status", "version", "baseUrl", "error"],
18942
- idField: "service",
18943
- select: args.select
18944
18985
  });
18945
- if (hadFailure) {
18946
- process.exitCode = 1;
18947
- }
18986
+ return data.toString();
18948
18987
  }
18949
- });
18988
+ };
18950
18989
  });
18951
18990
 
18952
- // src/cli/commands/config.ts
18953
- var exports_config = {};
18954
- __export(exports_config, {
18955
- config: () => config
18956
- });
18957
- var DEFAULT_PORTS, configInit, configSet, configGet, configShow, config;
18958
- var init_config2 = __esm(() => {
18959
- init_dist();
18960
- init_dist2();
18961
- init_config();
18962
- init_prompt2();
18963
- DEFAULT_PORTS = {
18964
- radarr: 7878,
18965
- sonarr: 8989,
18966
- lidarr: 8686,
18967
- readarr: 8787,
18968
- prowlarr: 9696,
18969
- bazarr: 6767
18970
- };
18971
- configInit = defineCommand({
18972
- meta: {
18973
- name: "init",
18974
- description: "Interactive setup wizard"
18975
- },
18976
- async run() {
18977
- if (!process.stdin.isTTY) {
18978
- consola.error("Config init requires an interactive terminal.\nUse `tsarr config set` or environment variables for non-interactive setup.");
18979
- process.exit(1);
18980
- }
18981
- consola.info(`Welcome to TsArr CLI setup!
18991
+ // src/generated/qbittorrent/core/serverSentEvents.gen.ts
18992
+ function createSseClient7({
18993
+ onRequest,
18994
+ onSseError,
18995
+ onSseEvent,
18996
+ responseTransformer,
18997
+ responseValidator,
18998
+ sseDefaultRetryDelay,
18999
+ sseMaxRetryAttempts,
19000
+ sseMaxRetryDelay,
19001
+ sseSleepFn,
19002
+ url,
19003
+ ...options
19004
+ }) {
19005
+ let lastEventId;
19006
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
19007
+ const createStream = async function* () {
19008
+ let retryDelay = sseDefaultRetryDelay ?? 3000;
19009
+ let attempt = 0;
19010
+ const signal = options.signal ?? new AbortController().signal;
19011
+ while (true) {
19012
+ if (signal.aborted)
19013
+ break;
19014
+ attempt++;
19015
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
19016
+ if (lastEventId !== undefined) {
19017
+ headers.set("Last-Event-ID", lastEventId);
19018
+ }
19019
+ try {
19020
+ const requestInit = {
19021
+ redirect: "follow",
19022
+ ...options,
19023
+ body: options.serializedBody,
19024
+ headers,
19025
+ signal
19026
+ };
19027
+ let request = new Request(url, requestInit);
19028
+ if (onRequest) {
19029
+ request = await onRequest(url, requestInit);
19030
+ }
19031
+ const _fetch = options.fetch ?? globalThis.fetch;
19032
+ const response = await _fetch(request);
19033
+ if (!response.ok)
19034
+ throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
19035
+ if (!response.body)
19036
+ throw new Error("No body in SSE response");
19037
+ const reader = response.body.pipeThrough(new TextDecoderStream).getReader();
19038
+ let buffer = "";
19039
+ const abortHandler = () => {
19040
+ try {
19041
+ reader.cancel();
19042
+ } catch {}
19043
+ };
19044
+ signal.addEventListener("abort", abortHandler);
19045
+ try {
19046
+ while (true) {
19047
+ const { done, value } = await reader.read();
19048
+ if (done)
19049
+ break;
19050
+ buffer += value;
19051
+ buffer = buffer.replace(/\r\n?/g, `
19052
+ `);
19053
+ const chunks = buffer.split(`
19054
+
19055
+ `);
19056
+ buffer = chunks.pop() ?? "";
19057
+ for (const chunk of chunks) {
19058
+ const lines = chunk.split(`
19059
+ `);
19060
+ const dataLines = [];
19061
+ let eventName;
19062
+ for (const line of lines) {
19063
+ if (line.startsWith("data:")) {
19064
+ dataLines.push(line.replace(/^data:\s*/, ""));
19065
+ } else if (line.startsWith("event:")) {
19066
+ eventName = line.replace(/^event:\s*/, "");
19067
+ } else if (line.startsWith("id:")) {
19068
+ lastEventId = line.replace(/^id:\s*/, "");
19069
+ } else if (line.startsWith("retry:")) {
19070
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
19071
+ if (!Number.isNaN(parsed)) {
19072
+ retryDelay = parsed;
19073
+ }
19074
+ }
19075
+ }
19076
+ let data;
19077
+ let parsedJson = false;
19078
+ if (dataLines.length) {
19079
+ const rawData = dataLines.join(`
19080
+ `);
19081
+ try {
19082
+ data = JSON.parse(rawData);
19083
+ parsedJson = true;
19084
+ } catch {
19085
+ data = rawData;
19086
+ }
19087
+ }
19088
+ if (parsedJson) {
19089
+ if (responseValidator) {
19090
+ await responseValidator(data);
19091
+ }
19092
+ if (responseTransformer) {
19093
+ data = await responseTransformer(data);
19094
+ }
19095
+ }
19096
+ onSseEvent?.({
19097
+ data,
19098
+ event: eventName,
19099
+ id: lastEventId,
19100
+ retry: retryDelay
19101
+ });
19102
+ if (dataLines.length) {
19103
+ yield data;
19104
+ }
19105
+ }
19106
+ }
19107
+ } finally {
19108
+ signal.removeEventListener("abort", abortHandler);
19109
+ reader.releaseLock();
19110
+ }
19111
+ break;
19112
+ } catch (error) {
19113
+ onSseError?.(error);
19114
+ if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
19115
+ break;
19116
+ }
19117
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
19118
+ await sleep(backoff);
19119
+ }
19120
+ }
19121
+ };
19122
+ const stream = createStream();
19123
+ return { stream };
19124
+ }
19125
+
19126
+ // src/generated/qbittorrent/core/pathSerializer.gen.ts
19127
+ var separatorArrayExplode7 = (style) => {
19128
+ switch (style) {
19129
+ case "label":
19130
+ return ".";
19131
+ case "matrix":
19132
+ return ";";
19133
+ case "simple":
19134
+ return ",";
19135
+ default:
19136
+ return "&";
19137
+ }
19138
+ }, separatorArrayNoExplode7 = (style) => {
19139
+ switch (style) {
19140
+ case "form":
19141
+ return ",";
19142
+ case "pipeDelimited":
19143
+ return "|";
19144
+ case "spaceDelimited":
19145
+ return "%20";
19146
+ default:
19147
+ return ",";
19148
+ }
19149
+ }, separatorObjectExplode7 = (style) => {
19150
+ switch (style) {
19151
+ case "label":
19152
+ return ".";
19153
+ case "matrix":
19154
+ return ";";
19155
+ case "simple":
19156
+ return ",";
19157
+ default:
19158
+ return "&";
19159
+ }
19160
+ }, serializeArrayParam7 = ({
19161
+ allowReserved,
19162
+ explode,
19163
+ name,
19164
+ style,
19165
+ value
19166
+ }) => {
19167
+ if (!explode) {
19168
+ const joinedValues2 = (allowReserved ? value : value.map((v2) => encodeURIComponent(v2))).join(separatorArrayNoExplode7(style));
19169
+ switch (style) {
19170
+ case "label":
19171
+ return `.${joinedValues2}`;
19172
+ case "matrix":
19173
+ return `;${name}=${joinedValues2}`;
19174
+ case "simple":
19175
+ return joinedValues2;
19176
+ default:
19177
+ return `${name}=${joinedValues2}`;
19178
+ }
19179
+ }
19180
+ const separator = separatorArrayExplode7(style);
19181
+ const joinedValues = value.map((v2) => {
19182
+ if (style === "label" || style === "simple") {
19183
+ return allowReserved ? v2 : encodeURIComponent(v2);
19184
+ }
19185
+ return serializePrimitiveParam7({
19186
+ allowReserved,
19187
+ name,
19188
+ value: v2
19189
+ });
19190
+ }).join(separator);
19191
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
19192
+ }, serializePrimitiveParam7 = ({
19193
+ allowReserved,
19194
+ name,
19195
+ value
19196
+ }) => {
19197
+ if (value === undefined || value === null) {
19198
+ return "";
19199
+ }
19200
+ if (typeof value === "object") {
19201
+ throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
19202
+ }
19203
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
19204
+ }, serializeObjectParam7 = ({
19205
+ allowReserved,
19206
+ explode,
19207
+ name,
19208
+ style,
19209
+ value,
19210
+ valueOnly
19211
+ }) => {
19212
+ if (value instanceof Date) {
19213
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
19214
+ }
19215
+ if (style !== "deepObject" && !explode) {
19216
+ let values = [];
19217
+ Object.entries(value).forEach(([key, v2]) => {
19218
+ values = [...values, key, allowReserved ? v2 : encodeURIComponent(v2)];
19219
+ });
19220
+ const joinedValues2 = values.join(",");
19221
+ switch (style) {
19222
+ case "form":
19223
+ return `${name}=${joinedValues2}`;
19224
+ case "label":
19225
+ return `.${joinedValues2}`;
19226
+ case "matrix":
19227
+ return `;${name}=${joinedValues2}`;
19228
+ default:
19229
+ return joinedValues2;
19230
+ }
19231
+ }
19232
+ const separator = separatorObjectExplode7(style);
19233
+ const joinedValues = Object.entries(value).map(([key, v2]) => serializePrimitiveParam7({
19234
+ allowReserved,
19235
+ name: style === "deepObject" ? `${name}[${key}]` : key,
19236
+ value: v2
19237
+ })).join(separator);
19238
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
19239
+ };
19240
+
19241
+ // src/generated/qbittorrent/core/utils.gen.ts
19242
+ function getValidRequestBody7(options) {
19243
+ const hasBody = options.body !== undefined;
19244
+ const isSerializedBody = hasBody && options.bodySerializer;
19245
+ if (isSerializedBody) {
19246
+ if ("serializedBody" in options) {
19247
+ const hasSerializedBody = options.serializedBody !== undefined && options.serializedBody !== "";
19248
+ return hasSerializedBody ? options.serializedBody : null;
19249
+ }
19250
+ return options.body !== "" ? options.body : null;
19251
+ }
19252
+ if (hasBody) {
19253
+ return options.body;
19254
+ }
19255
+ return;
19256
+ }
19257
+ var PATH_PARAM_RE7, defaultPathSerializer7 = ({ path, url: _url }) => {
19258
+ let url = _url;
19259
+ const matches = _url.match(PATH_PARAM_RE7);
19260
+ if (matches) {
19261
+ for (const match of matches) {
19262
+ let explode = false;
19263
+ let name = match.substring(1, match.length - 1);
19264
+ let style = "simple";
19265
+ if (name.endsWith("*")) {
19266
+ explode = true;
19267
+ name = name.substring(0, name.length - 1);
19268
+ }
19269
+ if (name.startsWith(".")) {
19270
+ name = name.substring(1);
19271
+ style = "label";
19272
+ } else if (name.startsWith(";")) {
19273
+ name = name.substring(1);
19274
+ style = "matrix";
19275
+ }
19276
+ const value = path[name];
19277
+ if (value === undefined || value === null) {
19278
+ continue;
19279
+ }
19280
+ if (Array.isArray(value)) {
19281
+ url = url.replace(match, serializeArrayParam7({ explode, name, style, value }));
19282
+ continue;
19283
+ }
19284
+ if (typeof value === "object") {
19285
+ url = url.replace(match, serializeObjectParam7({
19286
+ explode,
19287
+ name,
19288
+ style,
19289
+ value,
19290
+ valueOnly: true
19291
+ }));
19292
+ continue;
19293
+ }
19294
+ if (style === "matrix") {
19295
+ url = url.replace(match, `;${serializePrimitiveParam7({
19296
+ name,
19297
+ value
19298
+ })}`);
19299
+ continue;
19300
+ }
19301
+ const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
19302
+ url = url.replace(match, replaceValue);
19303
+ }
19304
+ }
19305
+ return url;
19306
+ }, getUrl7 = ({
19307
+ baseUrl,
19308
+ path,
19309
+ query,
19310
+ querySerializer,
19311
+ url: _url
19312
+ }) => {
19313
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
19314
+ let url = (baseUrl ?? "") + pathUrl;
19315
+ if (path) {
19316
+ url = defaultPathSerializer7({ path, url });
19317
+ }
19318
+ let search = query ? querySerializer(query) : "";
19319
+ if (search.startsWith("?")) {
19320
+ search = search.substring(1);
19321
+ }
19322
+ if (search) {
19323
+ url += `?${search}`;
19324
+ }
19325
+ return url;
19326
+ };
19327
+ var init_utils_gen13 = __esm(() => {
19328
+ PATH_PARAM_RE7 = /\{[^{}]+\}/g;
19329
+ });
19330
+
19331
+ // src/generated/qbittorrent/core/auth.gen.ts
19332
+ var getAuthToken7 = async (auth, callback) => {
19333
+ const token = typeof callback === "function" ? await callback(auth) : callback;
19334
+ if (!token) {
19335
+ return;
19336
+ }
19337
+ if (auth.scheme === "bearer") {
19338
+ return `Bearer ${token}`;
19339
+ }
19340
+ if (auth.scheme === "basic") {
19341
+ return `Basic ${btoa(token)}`;
19342
+ }
19343
+ return token;
19344
+ };
19345
+
19346
+ // src/generated/qbittorrent/client/utils.gen.ts
19347
+ class Interceptors7 {
19348
+ fns = [];
19349
+ clear() {
19350
+ this.fns = [];
19351
+ }
19352
+ eject(id) {
19353
+ const index = this.getInterceptorIndex(id);
19354
+ if (this.fns[index]) {
19355
+ this.fns[index] = null;
19356
+ }
19357
+ }
19358
+ exists(id) {
19359
+ const index = this.getInterceptorIndex(id);
19360
+ return Boolean(this.fns[index]);
19361
+ }
19362
+ getInterceptorIndex(id) {
19363
+ if (typeof id === "number") {
19364
+ return this.fns[id] ? id : -1;
19365
+ }
19366
+ return this.fns.indexOf(id);
19367
+ }
19368
+ update(id, fn) {
19369
+ const index = this.getInterceptorIndex(id);
19370
+ if (this.fns[index]) {
19371
+ this.fns[index] = fn;
19372
+ return id;
19373
+ }
19374
+ return false;
19375
+ }
19376
+ use(fn) {
19377
+ this.fns.push(fn);
19378
+ return this.fns.length - 1;
19379
+ }
19380
+ }
19381
+ var createQuerySerializer7 = ({
19382
+ parameters = {},
19383
+ ...args
19384
+ } = {}) => {
19385
+ const querySerializer = (queryParams) => {
19386
+ const search = [];
19387
+ if (queryParams && typeof queryParams === "object") {
19388
+ for (const name in queryParams) {
19389
+ const value = queryParams[name];
19390
+ if (value === undefined || value === null) {
19391
+ continue;
19392
+ }
19393
+ const options = parameters[name] || args;
19394
+ if (Array.isArray(value)) {
19395
+ const serializedArray = serializeArrayParam7({
19396
+ allowReserved: options.allowReserved,
19397
+ explode: true,
19398
+ name,
19399
+ style: "form",
19400
+ value,
19401
+ ...options.array
19402
+ });
19403
+ if (serializedArray)
19404
+ search.push(serializedArray);
19405
+ } else if (typeof value === "object") {
19406
+ const serializedObject = serializeObjectParam7({
19407
+ allowReserved: options.allowReserved,
19408
+ explode: true,
19409
+ name,
19410
+ style: "deepObject",
19411
+ value,
19412
+ ...options.object
19413
+ });
19414
+ if (serializedObject)
19415
+ search.push(serializedObject);
19416
+ } else {
19417
+ const serializedPrimitive = serializePrimitiveParam7({
19418
+ allowReserved: options.allowReserved,
19419
+ name,
19420
+ value
19421
+ });
19422
+ if (serializedPrimitive)
19423
+ search.push(serializedPrimitive);
19424
+ }
19425
+ }
19426
+ }
19427
+ return search.join("&");
19428
+ };
19429
+ return querySerializer;
19430
+ }, getParseAs7 = (contentType) => {
19431
+ if (!contentType) {
19432
+ return "stream";
19433
+ }
19434
+ const cleanContent = contentType.split(";")[0]?.trim();
19435
+ if (!cleanContent) {
19436
+ return;
19437
+ }
19438
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
19439
+ return "json";
19440
+ }
19441
+ if (cleanContent === "multipart/form-data") {
19442
+ return "formData";
19443
+ }
19444
+ if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
19445
+ return "blob";
19446
+ }
19447
+ if (cleanContent.startsWith("text/")) {
19448
+ return "text";
19449
+ }
19450
+ return;
19451
+ }, checkForExistence7 = (options, name) => {
19452
+ if (!name) {
19453
+ return false;
19454
+ }
19455
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
19456
+ return true;
19457
+ }
19458
+ return false;
19459
+ }, setAuthParams7 = async ({
19460
+ security,
19461
+ ...options
19462
+ }) => {
19463
+ for (const auth of security) {
19464
+ if (checkForExistence7(options, auth.name)) {
19465
+ continue;
19466
+ }
19467
+ const token = await getAuthToken7(auth, options.auth);
19468
+ if (!token) {
19469
+ continue;
19470
+ }
19471
+ const name = auth.name ?? "Authorization";
19472
+ switch (auth.in) {
19473
+ case "query":
19474
+ if (!options.query) {
19475
+ options.query = {};
19476
+ }
19477
+ options.query[name] = token;
19478
+ break;
19479
+ case "cookie":
19480
+ options.headers.append("Cookie", `${name}=${token}`);
19481
+ break;
19482
+ case "header":
19483
+ default:
19484
+ options.headers.set(name, token);
19485
+ break;
19486
+ }
19487
+ }
19488
+ }, buildUrl7 = (options) => getUrl7({
19489
+ baseUrl: options.baseUrl,
19490
+ path: options.path,
19491
+ query: options.query,
19492
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer7(options.querySerializer),
19493
+ url: options.url
19494
+ }), mergeConfigs7 = (a2, b2) => {
19495
+ const config = { ...a2, ...b2 };
19496
+ if (config.baseUrl?.endsWith("/")) {
19497
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
19498
+ }
19499
+ config.headers = mergeHeaders7(a2.headers, b2.headers);
19500
+ return config;
19501
+ }, headersEntries7 = (headers) => {
19502
+ const entries = [];
19503
+ headers.forEach((value, key) => {
19504
+ entries.push([key, value]);
19505
+ });
19506
+ return entries;
19507
+ }, mergeHeaders7 = (...headers) => {
19508
+ const mergedHeaders = new Headers;
19509
+ for (const header of headers) {
19510
+ if (!header) {
19511
+ continue;
19512
+ }
19513
+ const iterator = header instanceof Headers ? headersEntries7(header) : Object.entries(header);
19514
+ for (const [key, value] of iterator) {
19515
+ if (value === null) {
19516
+ mergedHeaders.delete(key);
19517
+ } else if (Array.isArray(value)) {
19518
+ for (const v2 of value) {
19519
+ mergedHeaders.append(key, v2);
19520
+ }
19521
+ } else if (value !== undefined) {
19522
+ mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
19523
+ }
19524
+ }
19525
+ }
19526
+ return mergedHeaders;
19527
+ }, createInterceptors7 = () => ({
19528
+ error: new Interceptors7,
19529
+ request: new Interceptors7,
19530
+ response: new Interceptors7
19531
+ }), defaultQuerySerializer7, defaultHeaders7, createConfig7 = (override = {}) => ({
19532
+ ...jsonBodySerializer7,
19533
+ headers: defaultHeaders7,
19534
+ parseAs: "auto",
19535
+ querySerializer: defaultQuerySerializer7,
19536
+ ...override
19537
+ });
19538
+ var init_utils_gen14 = __esm(() => {
19539
+ init_bodySerializer_gen7();
19540
+ init_utils_gen13();
19541
+ defaultQuerySerializer7 = createQuerySerializer7({
19542
+ allowReserved: false,
19543
+ array: {
19544
+ explode: true,
19545
+ style: "form"
19546
+ },
19547
+ object: {
19548
+ explode: true,
19549
+ style: "deepObject"
19550
+ }
19551
+ });
19552
+ defaultHeaders7 = {
19553
+ "Content-Type": "application/json"
19554
+ };
19555
+ });
19556
+
19557
+ // src/generated/qbittorrent/client/client.gen.ts
19558
+ var createClient7 = (config = {}) => {
19559
+ let _config = mergeConfigs7(createConfig7(), config);
19560
+ const getConfig = () => ({ ..._config });
19561
+ const setConfig = (config2) => {
19562
+ _config = mergeConfigs7(_config, config2);
19563
+ return getConfig();
19564
+ };
19565
+ const interceptors = createInterceptors7();
19566
+ const beforeRequest = async (options) => {
19567
+ const opts = {
19568
+ ..._config,
19569
+ ...options,
19570
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
19571
+ headers: mergeHeaders7(_config.headers, options.headers),
19572
+ serializedBody: undefined
19573
+ };
19574
+ if (opts.security) {
19575
+ await setAuthParams7({
19576
+ ...opts,
19577
+ security: opts.security
19578
+ });
19579
+ }
19580
+ if (opts.requestValidator) {
19581
+ await opts.requestValidator(opts);
19582
+ }
19583
+ if (opts.body !== undefined && opts.bodySerializer) {
19584
+ opts.serializedBody = opts.bodySerializer(opts.body);
19585
+ }
19586
+ if (opts.body === undefined || opts.serializedBody === "") {
19587
+ opts.headers.delete("Content-Type");
19588
+ }
19589
+ const resolvedOpts = opts;
19590
+ const url = buildUrl7(resolvedOpts);
19591
+ return { opts: resolvedOpts, url };
19592
+ };
19593
+ const request = async (options) => {
19594
+ const { opts, url } = await beforeRequest(options);
19595
+ const requestInit = {
19596
+ redirect: "follow",
19597
+ ...opts,
19598
+ body: getValidRequestBody7(opts)
19599
+ };
19600
+ let request2 = new Request(url, requestInit);
19601
+ for (const fn of interceptors.request.fns) {
19602
+ if (fn) {
19603
+ request2 = await fn(request2, opts);
19604
+ }
19605
+ }
19606
+ const _fetch = opts.fetch;
19607
+ let response;
19608
+ try {
19609
+ response = await _fetch(request2);
19610
+ } catch (error2) {
19611
+ let finalError2 = error2;
19612
+ for (const fn of interceptors.error.fns) {
19613
+ if (fn) {
19614
+ finalError2 = await fn(error2, undefined, request2, opts);
19615
+ }
19616
+ }
19617
+ finalError2 = finalError2 || {};
19618
+ if (opts.throwOnError) {
19619
+ throw finalError2;
19620
+ }
19621
+ return opts.responseStyle === "data" ? undefined : {
19622
+ error: finalError2,
19623
+ request: request2,
19624
+ response: undefined
19625
+ };
19626
+ }
19627
+ for (const fn of interceptors.response.fns) {
19628
+ if (fn) {
19629
+ response = await fn(response, request2, opts);
19630
+ }
19631
+ }
19632
+ const result = {
19633
+ request: request2,
19634
+ response
19635
+ };
19636
+ if (response.ok) {
19637
+ const parseAs = (opts.parseAs === "auto" ? getParseAs7(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
19638
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
19639
+ let emptyData;
19640
+ switch (parseAs) {
19641
+ case "arrayBuffer":
19642
+ case "blob":
19643
+ case "text":
19644
+ emptyData = await response[parseAs]();
19645
+ break;
19646
+ case "formData":
19647
+ emptyData = new FormData;
19648
+ break;
19649
+ case "stream":
19650
+ emptyData = response.body;
19651
+ break;
19652
+ case "json":
19653
+ default:
19654
+ emptyData = {};
19655
+ break;
19656
+ }
19657
+ return opts.responseStyle === "data" ? emptyData : {
19658
+ data: emptyData,
19659
+ ...result
19660
+ };
19661
+ }
19662
+ let data;
19663
+ switch (parseAs) {
19664
+ case "arrayBuffer":
19665
+ case "blob":
19666
+ case "formData":
19667
+ case "text":
19668
+ data = await response[parseAs]();
19669
+ break;
19670
+ case "json": {
19671
+ const text = await response.text();
19672
+ data = text ? JSON.parse(text) : {};
19673
+ break;
19674
+ }
19675
+ case "stream":
19676
+ return opts.responseStyle === "data" ? response.body : {
19677
+ data: response.body,
19678
+ ...result
19679
+ };
19680
+ }
19681
+ if (parseAs === "json") {
19682
+ if (opts.responseValidator) {
19683
+ await opts.responseValidator(data);
19684
+ }
19685
+ if (opts.responseTransformer) {
19686
+ data = await opts.responseTransformer(data);
19687
+ }
19688
+ }
19689
+ return opts.responseStyle === "data" ? data : {
19690
+ data,
19691
+ ...result
19692
+ };
19693
+ }
19694
+ const textError = await response.text();
19695
+ let jsonError;
19696
+ try {
19697
+ jsonError = JSON.parse(textError);
19698
+ } catch {}
19699
+ const error = jsonError ?? textError;
19700
+ let finalError = error;
19701
+ for (const fn of interceptors.error.fns) {
19702
+ if (fn) {
19703
+ finalError = await fn(error, response, request2, opts);
19704
+ }
19705
+ }
19706
+ finalError = finalError || {};
19707
+ if (opts.throwOnError) {
19708
+ throw finalError;
19709
+ }
19710
+ return opts.responseStyle === "data" ? undefined : {
19711
+ error: finalError,
19712
+ ...result
19713
+ };
19714
+ };
19715
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
19716
+ const makeSseFn = (method) => async (options) => {
19717
+ const { opts, url } = await beforeRequest(options);
19718
+ return createSseClient7({
19719
+ ...opts,
19720
+ body: opts.body,
19721
+ headers: opts.headers,
19722
+ method,
19723
+ onRequest: async (url2, init2) => {
19724
+ let request2 = new Request(url2, init2);
19725
+ for (const fn of interceptors.request.fns) {
19726
+ if (fn) {
19727
+ request2 = await fn(request2, opts);
19728
+ }
19729
+ }
19730
+ return request2;
19731
+ },
19732
+ serializedBody: getValidRequestBody7(opts),
19733
+ url
19734
+ });
19735
+ };
19736
+ const _buildUrl = (options) => buildUrl7({ ..._config, ...options });
19737
+ return {
19738
+ buildUrl: _buildUrl,
19739
+ connect: makeMethodFn("CONNECT"),
19740
+ delete: makeMethodFn("DELETE"),
19741
+ get: makeMethodFn("GET"),
19742
+ getConfig,
19743
+ head: makeMethodFn("HEAD"),
19744
+ interceptors,
19745
+ options: makeMethodFn("OPTIONS"),
19746
+ patch: makeMethodFn("PATCH"),
19747
+ post: makeMethodFn("POST"),
19748
+ put: makeMethodFn("PUT"),
19749
+ request,
19750
+ setConfig,
19751
+ sse: {
19752
+ connect: makeSseFn("CONNECT"),
19753
+ delete: makeSseFn("DELETE"),
19754
+ get: makeSseFn("GET"),
19755
+ head: makeSseFn("HEAD"),
19756
+ options: makeSseFn("OPTIONS"),
19757
+ patch: makeSseFn("PATCH"),
19758
+ post: makeSseFn("POST"),
19759
+ put: makeSseFn("PUT"),
19760
+ trace: makeSseFn("TRACE")
19761
+ },
19762
+ trace: makeMethodFn("TRACE")
19763
+ };
19764
+ };
19765
+ var init_client_gen13 = __esm(() => {
19766
+ init_utils_gen13();
19767
+ init_utils_gen14();
19768
+ });
19769
+
19770
+ // src/generated/qbittorrent/client/index.ts
19771
+ var init_client8 = __esm(() => {
19772
+ init_bodySerializer_gen7();
19773
+ init_client_gen13();
19774
+ init_utils_gen14();
19775
+ });
19776
+
19777
+ // src/generated/qbittorrent/client.gen.ts
19778
+ var client7;
19779
+ var init_client_gen14 = __esm(() => {
19780
+ init_client8();
19781
+ client7 = createClient7(createConfig7({ baseUrl: "http://localhost:8080/api/v2" }));
19782
+ });
19783
+
19784
+ // src/generated/qbittorrent/sdk.gen.ts
19785
+ var appVersionGet = (options) => (options?.client ?? client7).get({
19786
+ security: [{
19787
+ in: "cookie",
19788
+ name: "SID",
19789
+ type: "apiKey"
19790
+ }],
19791
+ url: "/app/version",
19792
+ ...options
19793
+ }), appWebapiVersionGet = (options) => (options?.client ?? client7).get({
19794
+ security: [{
19795
+ in: "cookie",
19796
+ name: "SID",
19797
+ type: "apiKey"
19798
+ }],
19799
+ url: "/app/webapiVersion",
19800
+ ...options
19801
+ }), transferInfoGet = (options) => (options?.client ?? client7).get({
19802
+ security: [{
19803
+ in: "cookie",
19804
+ name: "SID",
19805
+ type: "apiKey"
19806
+ }],
19807
+ url: "/transfer/info",
19808
+ ...options
19809
+ }), torrentsInfoPost = (options) => (options.client ?? client7).post({
19810
+ ...urlSearchParamsBodySerializer2,
19811
+ security: [{
19812
+ in: "cookie",
19813
+ name: "SID",
19814
+ type: "apiKey"
19815
+ }],
19816
+ url: "/torrents/info",
19817
+ ...options,
19818
+ headers: {
19819
+ "Content-Type": "application/x-www-form-urlencoded",
19820
+ ...options.headers
19821
+ }
19822
+ }), torrentsPausePost = (options) => (options.client ?? client7).post({
19823
+ ...urlSearchParamsBodySerializer2,
19824
+ security: [{
19825
+ in: "cookie",
19826
+ name: "SID",
19827
+ type: "apiKey"
19828
+ }],
19829
+ url: "/torrents/pause",
19830
+ ...options,
19831
+ headers: {
19832
+ "Content-Type": "application/x-www-form-urlencoded",
19833
+ ...options.headers
19834
+ }
19835
+ }), torrentsResumePost = (options) => (options.client ?? client7).post({
19836
+ ...urlSearchParamsBodySerializer2,
19837
+ security: [{
19838
+ in: "cookie",
19839
+ name: "SID",
19840
+ type: "apiKey"
19841
+ }],
19842
+ url: "/torrents/resume",
19843
+ ...options,
19844
+ headers: {
19845
+ "Content-Type": "application/x-www-form-urlencoded",
19846
+ ...options.headers
19847
+ }
19848
+ }), torrentsDeletePost = (options) => (options.client ?? client7).post({
19849
+ ...urlSearchParamsBodySerializer2,
19850
+ security: [{
19851
+ in: "cookie",
19852
+ name: "SID",
19853
+ type: "apiKey"
19854
+ }],
19855
+ url: "/torrents/delete",
19856
+ ...options,
19857
+ headers: {
19858
+ "Content-Type": "application/x-www-form-urlencoded",
19859
+ ...options.headers
19860
+ }
19861
+ });
19862
+ var init_sdk_gen7 = __esm(() => {
19863
+ init_client8();
19864
+ init_client_gen14();
19865
+ });
19866
+
19867
+ // src/generated/qbittorrent/index.ts
19868
+ var init_qbittorrent = __esm(() => {
19869
+ init_sdk_gen7();
19870
+ });
19871
+
19872
+ // src/clients/qbittorrent.ts
19873
+ var exports_qbittorrent = {};
19874
+ __export(exports_qbittorrent, {
19875
+ QBittorrentClient: () => QBittorrentClient
19876
+ });
19877
+
19878
+ class QBittorrentClient {
19879
+ baseUrl;
19880
+ username;
19881
+ password;
19882
+ sid = null;
19883
+ constructor(config) {
19884
+ if (!config.baseUrl) {
19885
+ throw new ConnectionError("No base URL provided");
19886
+ }
19887
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
19888
+ this.username = config.username;
19889
+ this.password = config.password;
19890
+ client7.setConfig({
19891
+ baseUrl: `${this.baseUrl}/api/v2`,
19892
+ auth: () => this.ensureAuth()
19893
+ });
19894
+ }
19895
+ async ensureAuth() {
19896
+ if (!this.sid) {
19897
+ await this.login();
19898
+ }
19899
+ return this.sid;
19900
+ }
19901
+ async login() {
19902
+ const response = await fetch(`${this.baseUrl}/api/v2/auth/login`, {
19903
+ method: "POST",
19904
+ headers: {
19905
+ "Content-Type": "application/x-www-form-urlencoded",
19906
+ Referer: this.baseUrl
19907
+ },
19908
+ body: new URLSearchParams({
19909
+ username: this.username,
19910
+ password: this.password
19911
+ })
19912
+ });
19913
+ if (!response.ok) {
19914
+ throw new ConnectionError(`qBittorrent login failed (${response.status})`);
19915
+ }
19916
+ const text = await response.text();
19917
+ if (text.trim() !== "Ok.") {
19918
+ throw new ConnectionError("qBittorrent authentication failed: invalid username or password");
19919
+ }
19920
+ const setCookie = response.headers.get("set-cookie");
19921
+ const sidMatch = setCookie?.match(/SID=([^;]+)/);
19922
+ if (!sidMatch) {
19923
+ throw new ConnectionError("qBittorrent login succeeded but no SID cookie received");
19924
+ }
19925
+ this.sid = sidMatch[1];
19926
+ }
19927
+ async getAppVersion() {
19928
+ const result = await appVersionGet();
19929
+ return result.data ?? "";
19930
+ }
19931
+ async getApiVersion() {
19932
+ const result = await appWebapiVersionGet();
19933
+ return result.data ?? "";
19934
+ }
19935
+ async getSystemStatus() {
19936
+ const version = await this.getAppVersion();
19937
+ return { version };
19938
+ }
19939
+ async getTransferInfo() {
19940
+ const result = await transferInfoGet();
19941
+ return result.data ?? {};
19942
+ }
19943
+ async getTorrents(filter) {
19944
+ const result = await torrentsInfoPost({
19945
+ body: {
19946
+ ...filter ? { filter } : {}
19947
+ }
19948
+ });
19949
+ return result.data ?? [];
19950
+ }
19951
+ async pauseTorrents(hashes) {
19952
+ await torrentsPausePost({
19953
+ body: { hashes: hashes.split("|") }
19954
+ });
19955
+ }
19956
+ async resumeTorrents(hashes) {
19957
+ await torrentsResumePost({
19958
+ body: { hashes: hashes.split("|") }
19959
+ });
19960
+ }
19961
+ async deleteTorrents(hashes, deleteFiles = false) {
19962
+ await torrentsDeletePost({
19963
+ body: { hashes: hashes.split("|"), deleteFiles }
19964
+ });
19965
+ }
19966
+ }
19967
+ var init_qbittorrent2 = __esm(() => {
19968
+ init_errors();
19969
+ init_client_gen14();
19970
+ init_qbittorrent();
19971
+ });
19972
+
19973
+ // src/cli/commands/qbit.ts
19974
+ var exports_qbit = {};
19975
+ __export(exports_qbit, {
19976
+ resources: () => resources7,
19977
+ qbit: () => qbit
19978
+ });
19979
+ var resources7, qbit;
19980
+ var init_qbit = __esm(() => {
19981
+ init_qbittorrent2();
19982
+ init_service();
19983
+ resources7 = [
19984
+ {
19985
+ name: "torrents",
19986
+ description: "Manage torrents",
19987
+ actions: [
19988
+ {
19989
+ name: "list",
19990
+ description: "List torrents",
19991
+ args: [
19992
+ {
19993
+ name: "filter",
19994
+ description: "Filter (all|downloading|seeding|completed|paused|active|inactive|stalled|errored)"
19995
+ }
19996
+ ],
19997
+ columns: ["hash", "name", "state", "progress", "size", "dlspeed", "upspeed"],
19998
+ idField: "hash",
19999
+ run: (c3, a2) => c3.getTorrents(a2.filter)
20000
+ },
20001
+ {
20002
+ name: "pause",
20003
+ description: "Pause torrents",
20004
+ args: [
20005
+ {
20006
+ name: "hashes",
20007
+ description: 'Torrent hashes (comma-separated, or "all")',
20008
+ required: true
20009
+ }
20010
+ ],
20011
+ run: (c3, a2) => c3.pauseTorrents(a2.hashes)
20012
+ },
20013
+ {
20014
+ name: "resume",
20015
+ description: "Resume torrents",
20016
+ args: [
20017
+ {
20018
+ name: "hashes",
20019
+ description: 'Torrent hashes (comma-separated, or "all")',
20020
+ required: true
20021
+ }
20022
+ ],
20023
+ run: (c3, a2) => c3.resumeTorrents(a2.hashes)
20024
+ },
20025
+ {
20026
+ name: "delete",
20027
+ description: "Delete torrents",
20028
+ args: [
20029
+ {
20030
+ name: "hashes",
20031
+ description: 'Torrent hashes (comma-separated, or "all")',
20032
+ required: true
20033
+ },
20034
+ {
20035
+ name: "delete-files",
20036
+ description: "Also delete downloaded files",
20037
+ type: "boolean"
20038
+ }
20039
+ ],
20040
+ confirmMessage: "Are you sure you want to delete these torrents?",
20041
+ run: (c3, a2) => c3.deleteTorrents(a2.hashes, a2["delete-files"])
20042
+ }
20043
+ ]
20044
+ },
20045
+ {
20046
+ name: "status",
20047
+ description: "Transfer status",
20048
+ actions: [
20049
+ {
20050
+ name: "show",
20051
+ description: "Show transfer info (speed, connections)",
20052
+ columns: [
20053
+ "connection_status",
20054
+ "dl_info_speed",
20055
+ "dl_info_data",
20056
+ "up_info_speed",
20057
+ "up_info_data",
20058
+ "dht_nodes"
20059
+ ],
20060
+ run: (c3) => c3.getTransferInfo()
20061
+ }
20062
+ ]
20063
+ }
20064
+ ];
20065
+ qbit = buildServiceCommand("qbittorrent", "Manage qBittorrent", (config) => new QBittorrentClient(config), resources7);
20066
+ });
20067
+
20068
+ // src/generated/seerr/core/serverSentEvents.gen.ts
20069
+ function createSseClient8({
20070
+ onRequest,
20071
+ onSseError,
20072
+ onSseEvent,
20073
+ responseTransformer,
20074
+ responseValidator,
20075
+ sseDefaultRetryDelay,
20076
+ sseMaxRetryAttempts,
20077
+ sseMaxRetryDelay,
20078
+ sseSleepFn,
20079
+ url,
20080
+ ...options
20081
+ }) {
20082
+ let lastEventId;
20083
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
20084
+ const createStream = async function* () {
20085
+ let retryDelay = sseDefaultRetryDelay ?? 3000;
20086
+ let attempt = 0;
20087
+ const signal = options.signal ?? new AbortController().signal;
20088
+ while (true) {
20089
+ if (signal.aborted)
20090
+ break;
20091
+ attempt++;
20092
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
20093
+ if (lastEventId !== undefined) {
20094
+ headers.set("Last-Event-ID", lastEventId);
20095
+ }
20096
+ try {
20097
+ const requestInit = {
20098
+ redirect: "follow",
20099
+ ...options,
20100
+ body: options.serializedBody,
20101
+ headers,
20102
+ signal
20103
+ };
20104
+ let request = new Request(url, requestInit);
20105
+ if (onRequest) {
20106
+ request = await onRequest(url, requestInit);
20107
+ }
20108
+ const _fetch = options.fetch ?? globalThis.fetch;
20109
+ const response = await _fetch(request);
20110
+ if (!response.ok)
20111
+ throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
20112
+ if (!response.body)
20113
+ throw new Error("No body in SSE response");
20114
+ const reader = response.body.pipeThrough(new TextDecoderStream).getReader();
20115
+ let buffer = "";
20116
+ const abortHandler = () => {
20117
+ try {
20118
+ reader.cancel();
20119
+ } catch {}
20120
+ };
20121
+ signal.addEventListener("abort", abortHandler);
20122
+ try {
20123
+ while (true) {
20124
+ const { done, value } = await reader.read();
20125
+ if (done)
20126
+ break;
20127
+ buffer += value;
20128
+ buffer = buffer.replace(/\r\n?/g, `
20129
+ `);
20130
+ const chunks = buffer.split(`
20131
+
20132
+ `);
20133
+ buffer = chunks.pop() ?? "";
20134
+ for (const chunk of chunks) {
20135
+ const lines = chunk.split(`
20136
+ `);
20137
+ const dataLines = [];
20138
+ let eventName;
20139
+ for (const line of lines) {
20140
+ if (line.startsWith("data:")) {
20141
+ dataLines.push(line.replace(/^data:\s*/, ""));
20142
+ } else if (line.startsWith("event:")) {
20143
+ eventName = line.replace(/^event:\s*/, "");
20144
+ } else if (line.startsWith("id:")) {
20145
+ lastEventId = line.replace(/^id:\s*/, "");
20146
+ } else if (line.startsWith("retry:")) {
20147
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
20148
+ if (!Number.isNaN(parsed)) {
20149
+ retryDelay = parsed;
20150
+ }
20151
+ }
20152
+ }
20153
+ let data;
20154
+ let parsedJson = false;
20155
+ if (dataLines.length) {
20156
+ const rawData = dataLines.join(`
20157
+ `);
20158
+ try {
20159
+ data = JSON.parse(rawData);
20160
+ parsedJson = true;
20161
+ } catch {
20162
+ data = rawData;
20163
+ }
20164
+ }
20165
+ if (parsedJson) {
20166
+ if (responseValidator) {
20167
+ await responseValidator(data);
20168
+ }
20169
+ if (responseTransformer) {
20170
+ data = await responseTransformer(data);
20171
+ }
20172
+ }
20173
+ onSseEvent?.({
20174
+ data,
20175
+ event: eventName,
20176
+ id: lastEventId,
20177
+ retry: retryDelay
20178
+ });
20179
+ if (dataLines.length) {
20180
+ yield data;
20181
+ }
20182
+ }
20183
+ }
20184
+ } finally {
20185
+ signal.removeEventListener("abort", abortHandler);
20186
+ reader.releaseLock();
20187
+ }
20188
+ break;
20189
+ } catch (error) {
20190
+ onSseError?.(error);
20191
+ if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
20192
+ break;
20193
+ }
20194
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
20195
+ await sleep(backoff);
20196
+ }
20197
+ }
20198
+ };
20199
+ const stream = createStream();
20200
+ return { stream };
20201
+ }
20202
+
20203
+ // src/generated/seerr/core/pathSerializer.gen.ts
20204
+ var separatorArrayExplode8 = (style) => {
20205
+ switch (style) {
20206
+ case "label":
20207
+ return ".";
20208
+ case "matrix":
20209
+ return ";";
20210
+ case "simple":
20211
+ return ",";
20212
+ default:
20213
+ return "&";
20214
+ }
20215
+ }, separatorArrayNoExplode8 = (style) => {
20216
+ switch (style) {
20217
+ case "form":
20218
+ return ",";
20219
+ case "pipeDelimited":
20220
+ return "|";
20221
+ case "spaceDelimited":
20222
+ return "%20";
20223
+ default:
20224
+ return ",";
20225
+ }
20226
+ }, separatorObjectExplode8 = (style) => {
20227
+ switch (style) {
20228
+ case "label":
20229
+ return ".";
20230
+ case "matrix":
20231
+ return ";";
20232
+ case "simple":
20233
+ return ",";
20234
+ default:
20235
+ return "&";
20236
+ }
20237
+ }, serializeArrayParam8 = ({
20238
+ allowReserved,
20239
+ explode,
20240
+ name,
20241
+ style,
20242
+ value
20243
+ }) => {
20244
+ if (!explode) {
20245
+ const joinedValues2 = (allowReserved ? value : value.map((v2) => encodeURIComponent(v2))).join(separatorArrayNoExplode8(style));
20246
+ switch (style) {
20247
+ case "label":
20248
+ return `.${joinedValues2}`;
20249
+ case "matrix":
20250
+ return `;${name}=${joinedValues2}`;
20251
+ case "simple":
20252
+ return joinedValues2;
20253
+ default:
20254
+ return `${name}=${joinedValues2}`;
20255
+ }
20256
+ }
20257
+ const separator = separatorArrayExplode8(style);
20258
+ const joinedValues = value.map((v2) => {
20259
+ if (style === "label" || style === "simple") {
20260
+ return allowReserved ? v2 : encodeURIComponent(v2);
20261
+ }
20262
+ return serializePrimitiveParam8({
20263
+ allowReserved,
20264
+ name,
20265
+ value: v2
20266
+ });
20267
+ }).join(separator);
20268
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
20269
+ }, serializePrimitiveParam8 = ({
20270
+ allowReserved,
20271
+ name,
20272
+ value
20273
+ }) => {
20274
+ if (value === undefined || value === null) {
20275
+ return "";
20276
+ }
20277
+ if (typeof value === "object") {
20278
+ throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
20279
+ }
20280
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
20281
+ }, serializeObjectParam8 = ({
20282
+ allowReserved,
20283
+ explode,
20284
+ name,
20285
+ style,
20286
+ value,
20287
+ valueOnly
20288
+ }) => {
20289
+ if (value instanceof Date) {
20290
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
20291
+ }
20292
+ if (style !== "deepObject" && !explode) {
20293
+ let values = [];
20294
+ Object.entries(value).forEach(([key, v2]) => {
20295
+ values = [...values, key, allowReserved ? v2 : encodeURIComponent(v2)];
20296
+ });
20297
+ const joinedValues2 = values.join(",");
20298
+ switch (style) {
20299
+ case "form":
20300
+ return `${name}=${joinedValues2}`;
20301
+ case "label":
20302
+ return `.${joinedValues2}`;
20303
+ case "matrix":
20304
+ return `;${name}=${joinedValues2}`;
20305
+ default:
20306
+ return joinedValues2;
20307
+ }
20308
+ }
20309
+ const separator = separatorObjectExplode8(style);
20310
+ const joinedValues = Object.entries(value).map(([key, v2]) => serializePrimitiveParam8({
20311
+ allowReserved,
20312
+ name: style === "deepObject" ? `${name}[${key}]` : key,
20313
+ value: v2
20314
+ })).join(separator);
20315
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
20316
+ };
20317
+
20318
+ // src/generated/seerr/core/utils.gen.ts
20319
+ function getValidRequestBody8(options) {
20320
+ const hasBody = options.body !== undefined;
20321
+ const isSerializedBody = hasBody && options.bodySerializer;
20322
+ if (isSerializedBody) {
20323
+ if ("serializedBody" in options) {
20324
+ const hasSerializedBody = options.serializedBody !== undefined && options.serializedBody !== "";
20325
+ return hasSerializedBody ? options.serializedBody : null;
20326
+ }
20327
+ return options.body !== "" ? options.body : null;
20328
+ }
20329
+ if (hasBody) {
20330
+ return options.body;
20331
+ }
20332
+ return;
20333
+ }
20334
+ var PATH_PARAM_RE8, defaultPathSerializer8 = ({ path, url: _url }) => {
20335
+ let url = _url;
20336
+ const matches = _url.match(PATH_PARAM_RE8);
20337
+ if (matches) {
20338
+ for (const match of matches) {
20339
+ let explode = false;
20340
+ let name = match.substring(1, match.length - 1);
20341
+ let style = "simple";
20342
+ if (name.endsWith("*")) {
20343
+ explode = true;
20344
+ name = name.substring(0, name.length - 1);
20345
+ }
20346
+ if (name.startsWith(".")) {
20347
+ name = name.substring(1);
20348
+ style = "label";
20349
+ } else if (name.startsWith(";")) {
20350
+ name = name.substring(1);
20351
+ style = "matrix";
20352
+ }
20353
+ const value = path[name];
20354
+ if (value === undefined || value === null) {
20355
+ continue;
20356
+ }
20357
+ if (Array.isArray(value)) {
20358
+ url = url.replace(match, serializeArrayParam8({ explode, name, style, value }));
20359
+ continue;
20360
+ }
20361
+ if (typeof value === "object") {
20362
+ url = url.replace(match, serializeObjectParam8({
20363
+ explode,
20364
+ name,
20365
+ style,
20366
+ value,
20367
+ valueOnly: true
20368
+ }));
20369
+ continue;
20370
+ }
20371
+ if (style === "matrix") {
20372
+ url = url.replace(match, `;${serializePrimitiveParam8({
20373
+ name,
20374
+ value
20375
+ })}`);
20376
+ continue;
20377
+ }
20378
+ const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
20379
+ url = url.replace(match, replaceValue);
20380
+ }
20381
+ }
20382
+ return url;
20383
+ }, getUrl8 = ({
20384
+ baseUrl,
20385
+ path,
20386
+ query,
20387
+ querySerializer,
20388
+ url: _url
20389
+ }) => {
20390
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
20391
+ let url = (baseUrl ?? "") + pathUrl;
20392
+ if (path) {
20393
+ url = defaultPathSerializer8({ path, url });
20394
+ }
20395
+ let search = query ? querySerializer(query) : "";
20396
+ if (search.startsWith("?")) {
20397
+ search = search.substring(1);
20398
+ }
20399
+ if (search) {
20400
+ url += `?${search}`;
20401
+ }
20402
+ return url;
20403
+ };
20404
+ var init_utils_gen15 = __esm(() => {
20405
+ PATH_PARAM_RE8 = /\{[^{}]+\}/g;
20406
+ });
20407
+
20408
+ // src/generated/seerr/core/auth.gen.ts
20409
+ var getAuthToken8 = async (auth, callback) => {
20410
+ const token = typeof callback === "function" ? await callback(auth) : callback;
20411
+ if (!token) {
20412
+ return;
20413
+ }
20414
+ if (auth.scheme === "bearer") {
20415
+ return `Bearer ${token}`;
20416
+ }
20417
+ if (auth.scheme === "basic") {
20418
+ return `Basic ${btoa(token)}`;
20419
+ }
20420
+ return token;
20421
+ };
20422
+
20423
+ // src/generated/seerr/core/bodySerializer.gen.ts
20424
+ var jsonBodySerializer8;
20425
+ var init_bodySerializer_gen8 = __esm(() => {
20426
+ jsonBodySerializer8 = {
20427
+ bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
20428
+ };
20429
+ });
20430
+
20431
+ // src/generated/seerr/client/utils.gen.ts
20432
+ class Interceptors8 {
20433
+ fns = [];
20434
+ clear() {
20435
+ this.fns = [];
20436
+ }
20437
+ eject(id) {
20438
+ const index = this.getInterceptorIndex(id);
20439
+ if (this.fns[index]) {
20440
+ this.fns[index] = null;
20441
+ }
20442
+ }
20443
+ exists(id) {
20444
+ const index = this.getInterceptorIndex(id);
20445
+ return Boolean(this.fns[index]);
20446
+ }
20447
+ getInterceptorIndex(id) {
20448
+ if (typeof id === "number") {
20449
+ return this.fns[id] ? id : -1;
20450
+ }
20451
+ return this.fns.indexOf(id);
20452
+ }
20453
+ update(id, fn) {
20454
+ const index = this.getInterceptorIndex(id);
20455
+ if (this.fns[index]) {
20456
+ this.fns[index] = fn;
20457
+ return id;
20458
+ }
20459
+ return false;
20460
+ }
20461
+ use(fn) {
20462
+ this.fns.push(fn);
20463
+ return this.fns.length - 1;
20464
+ }
20465
+ }
20466
+ var createQuerySerializer8 = ({
20467
+ parameters = {},
20468
+ ...args
20469
+ } = {}) => {
20470
+ const querySerializer = (queryParams) => {
20471
+ const search = [];
20472
+ if (queryParams && typeof queryParams === "object") {
20473
+ for (const name in queryParams) {
20474
+ const value = queryParams[name];
20475
+ if (value === undefined || value === null) {
20476
+ continue;
20477
+ }
20478
+ const options = parameters[name] || args;
20479
+ if (Array.isArray(value)) {
20480
+ const serializedArray = serializeArrayParam8({
20481
+ allowReserved: options.allowReserved,
20482
+ explode: true,
20483
+ name,
20484
+ style: "form",
20485
+ value,
20486
+ ...options.array
20487
+ });
20488
+ if (serializedArray)
20489
+ search.push(serializedArray);
20490
+ } else if (typeof value === "object") {
20491
+ const serializedObject = serializeObjectParam8({
20492
+ allowReserved: options.allowReserved,
20493
+ explode: true,
20494
+ name,
20495
+ style: "deepObject",
20496
+ value,
20497
+ ...options.object
20498
+ });
20499
+ if (serializedObject)
20500
+ search.push(serializedObject);
20501
+ } else {
20502
+ const serializedPrimitive = serializePrimitiveParam8({
20503
+ allowReserved: options.allowReserved,
20504
+ name,
20505
+ value
20506
+ });
20507
+ if (serializedPrimitive)
20508
+ search.push(serializedPrimitive);
20509
+ }
20510
+ }
20511
+ }
20512
+ return search.join("&");
20513
+ };
20514
+ return querySerializer;
20515
+ }, getParseAs8 = (contentType) => {
20516
+ if (!contentType) {
20517
+ return "stream";
20518
+ }
20519
+ const cleanContent = contentType.split(";")[0]?.trim();
20520
+ if (!cleanContent) {
20521
+ return;
20522
+ }
20523
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
20524
+ return "json";
20525
+ }
20526
+ if (cleanContent === "multipart/form-data") {
20527
+ return "formData";
20528
+ }
20529
+ if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
20530
+ return "blob";
20531
+ }
20532
+ if (cleanContent.startsWith("text/")) {
20533
+ return "text";
20534
+ }
20535
+ return;
20536
+ }, checkForExistence8 = (options, name) => {
20537
+ if (!name) {
20538
+ return false;
20539
+ }
20540
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
20541
+ return true;
20542
+ }
20543
+ return false;
20544
+ }, setAuthParams8 = async ({
20545
+ security,
20546
+ ...options
20547
+ }) => {
20548
+ for (const auth of security) {
20549
+ if (checkForExistence8(options, auth.name)) {
20550
+ continue;
20551
+ }
20552
+ const token = await getAuthToken8(auth, options.auth);
20553
+ if (!token) {
20554
+ continue;
20555
+ }
20556
+ const name = auth.name ?? "Authorization";
20557
+ switch (auth.in) {
20558
+ case "query":
20559
+ if (!options.query) {
20560
+ options.query = {};
20561
+ }
20562
+ options.query[name] = token;
20563
+ break;
20564
+ case "cookie":
20565
+ options.headers.append("Cookie", `${name}=${token}`);
20566
+ break;
20567
+ case "header":
20568
+ default:
20569
+ options.headers.set(name, token);
20570
+ break;
20571
+ }
20572
+ }
20573
+ }, buildUrl8 = (options) => getUrl8({
20574
+ baseUrl: options.baseUrl,
20575
+ path: options.path,
20576
+ query: options.query,
20577
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer8(options.querySerializer),
20578
+ url: options.url
20579
+ }), mergeConfigs8 = (a2, b2) => {
20580
+ const config = { ...a2, ...b2 };
20581
+ if (config.baseUrl?.endsWith("/")) {
20582
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
20583
+ }
20584
+ config.headers = mergeHeaders8(a2.headers, b2.headers);
20585
+ return config;
20586
+ }, headersEntries8 = (headers) => {
20587
+ const entries = [];
20588
+ headers.forEach((value, key) => {
20589
+ entries.push([key, value]);
20590
+ });
20591
+ return entries;
20592
+ }, mergeHeaders8 = (...headers) => {
20593
+ const mergedHeaders = new Headers;
20594
+ for (const header of headers) {
20595
+ if (!header) {
20596
+ continue;
20597
+ }
20598
+ const iterator = header instanceof Headers ? headersEntries8(header) : Object.entries(header);
20599
+ for (const [key, value] of iterator) {
20600
+ if (value === null) {
20601
+ mergedHeaders.delete(key);
20602
+ } else if (Array.isArray(value)) {
20603
+ for (const v2 of value) {
20604
+ mergedHeaders.append(key, v2);
20605
+ }
20606
+ } else if (value !== undefined) {
20607
+ mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
20608
+ }
20609
+ }
20610
+ }
20611
+ return mergedHeaders;
20612
+ }, createInterceptors8 = () => ({
20613
+ error: new Interceptors8,
20614
+ request: new Interceptors8,
20615
+ response: new Interceptors8
20616
+ }), defaultQuerySerializer8, defaultHeaders8, createConfig8 = (override = {}) => ({
20617
+ ...jsonBodySerializer8,
20618
+ headers: defaultHeaders8,
20619
+ parseAs: "auto",
20620
+ querySerializer: defaultQuerySerializer8,
20621
+ ...override
20622
+ });
20623
+ var init_utils_gen16 = __esm(() => {
20624
+ init_bodySerializer_gen8();
20625
+ init_utils_gen15();
20626
+ defaultQuerySerializer8 = createQuerySerializer8({
20627
+ allowReserved: false,
20628
+ array: {
20629
+ explode: true,
20630
+ style: "form"
20631
+ },
20632
+ object: {
20633
+ explode: true,
20634
+ style: "deepObject"
20635
+ }
20636
+ });
20637
+ defaultHeaders8 = {
20638
+ "Content-Type": "application/json"
20639
+ };
20640
+ });
20641
+
20642
+ // src/generated/seerr/client/client.gen.ts
20643
+ var createClient8 = (config = {}) => {
20644
+ let _config = mergeConfigs8(createConfig8(), config);
20645
+ const getConfig = () => ({ ..._config });
20646
+ const setConfig = (config2) => {
20647
+ _config = mergeConfigs8(_config, config2);
20648
+ return getConfig();
20649
+ };
20650
+ const interceptors = createInterceptors8();
20651
+ const beforeRequest = async (options) => {
20652
+ const opts = {
20653
+ ..._config,
20654
+ ...options,
20655
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
20656
+ headers: mergeHeaders8(_config.headers, options.headers),
20657
+ serializedBody: undefined
20658
+ };
20659
+ if (opts.security) {
20660
+ await setAuthParams8({
20661
+ ...opts,
20662
+ security: opts.security
20663
+ });
20664
+ }
20665
+ if (opts.requestValidator) {
20666
+ await opts.requestValidator(opts);
20667
+ }
20668
+ if (opts.body !== undefined && opts.bodySerializer) {
20669
+ opts.serializedBody = opts.bodySerializer(opts.body);
20670
+ }
20671
+ if (opts.body === undefined || opts.serializedBody === "") {
20672
+ opts.headers.delete("Content-Type");
20673
+ }
20674
+ const resolvedOpts = opts;
20675
+ const url = buildUrl8(resolvedOpts);
20676
+ return { opts: resolvedOpts, url };
20677
+ };
20678
+ const request = async (options) => {
20679
+ const { opts, url } = await beforeRequest(options);
20680
+ const requestInit = {
20681
+ redirect: "follow",
20682
+ ...opts,
20683
+ body: getValidRequestBody8(opts)
20684
+ };
20685
+ let request2 = new Request(url, requestInit);
20686
+ for (const fn of interceptors.request.fns) {
20687
+ if (fn) {
20688
+ request2 = await fn(request2, opts);
20689
+ }
20690
+ }
20691
+ const _fetch = opts.fetch;
20692
+ let response;
20693
+ try {
20694
+ response = await _fetch(request2);
20695
+ } catch (error2) {
20696
+ let finalError2 = error2;
20697
+ for (const fn of interceptors.error.fns) {
20698
+ if (fn) {
20699
+ finalError2 = await fn(error2, undefined, request2, opts);
20700
+ }
20701
+ }
20702
+ finalError2 = finalError2 || {};
20703
+ if (opts.throwOnError) {
20704
+ throw finalError2;
20705
+ }
20706
+ return opts.responseStyle === "data" ? undefined : {
20707
+ error: finalError2,
20708
+ request: request2,
20709
+ response: undefined
20710
+ };
20711
+ }
20712
+ for (const fn of interceptors.response.fns) {
20713
+ if (fn) {
20714
+ response = await fn(response, request2, opts);
20715
+ }
20716
+ }
20717
+ const result = {
20718
+ request: request2,
20719
+ response
20720
+ };
20721
+ if (response.ok) {
20722
+ const parseAs = (opts.parseAs === "auto" ? getParseAs8(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
20723
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
20724
+ let emptyData;
20725
+ switch (parseAs) {
20726
+ case "arrayBuffer":
20727
+ case "blob":
20728
+ case "text":
20729
+ emptyData = await response[parseAs]();
20730
+ break;
20731
+ case "formData":
20732
+ emptyData = new FormData;
20733
+ break;
20734
+ case "stream":
20735
+ emptyData = response.body;
20736
+ break;
20737
+ case "json":
20738
+ default:
20739
+ emptyData = {};
20740
+ break;
20741
+ }
20742
+ return opts.responseStyle === "data" ? emptyData : {
20743
+ data: emptyData,
20744
+ ...result
20745
+ };
20746
+ }
20747
+ let data;
20748
+ switch (parseAs) {
20749
+ case "arrayBuffer":
20750
+ case "blob":
20751
+ case "formData":
20752
+ case "text":
20753
+ data = await response[parseAs]();
20754
+ break;
20755
+ case "json": {
20756
+ const text = await response.text();
20757
+ data = text ? JSON.parse(text) : {};
20758
+ break;
20759
+ }
20760
+ case "stream":
20761
+ return opts.responseStyle === "data" ? response.body : {
20762
+ data: response.body,
20763
+ ...result
20764
+ };
20765
+ }
20766
+ if (parseAs === "json") {
20767
+ if (opts.responseValidator) {
20768
+ await opts.responseValidator(data);
20769
+ }
20770
+ if (opts.responseTransformer) {
20771
+ data = await opts.responseTransformer(data);
20772
+ }
20773
+ }
20774
+ return opts.responseStyle === "data" ? data : {
20775
+ data,
20776
+ ...result
20777
+ };
20778
+ }
20779
+ const textError = await response.text();
20780
+ let jsonError;
20781
+ try {
20782
+ jsonError = JSON.parse(textError);
20783
+ } catch {}
20784
+ const error = jsonError ?? textError;
20785
+ let finalError = error;
20786
+ for (const fn of interceptors.error.fns) {
20787
+ if (fn) {
20788
+ finalError = await fn(error, response, request2, opts);
20789
+ }
20790
+ }
20791
+ finalError = finalError || {};
20792
+ if (opts.throwOnError) {
20793
+ throw finalError;
20794
+ }
20795
+ return opts.responseStyle === "data" ? undefined : {
20796
+ error: finalError,
20797
+ ...result
20798
+ };
20799
+ };
20800
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
20801
+ const makeSseFn = (method) => async (options) => {
20802
+ const { opts, url } = await beforeRequest(options);
20803
+ return createSseClient8({
20804
+ ...opts,
20805
+ body: opts.body,
20806
+ headers: opts.headers,
20807
+ method,
20808
+ onRequest: async (url2, init2) => {
20809
+ let request2 = new Request(url2, init2);
20810
+ for (const fn of interceptors.request.fns) {
20811
+ if (fn) {
20812
+ request2 = await fn(request2, opts);
20813
+ }
20814
+ }
20815
+ return request2;
20816
+ },
20817
+ serializedBody: getValidRequestBody8(opts),
20818
+ url
20819
+ });
20820
+ };
20821
+ const _buildUrl = (options) => buildUrl8({ ..._config, ...options });
20822
+ return {
20823
+ buildUrl: _buildUrl,
20824
+ connect: makeMethodFn("CONNECT"),
20825
+ delete: makeMethodFn("DELETE"),
20826
+ get: makeMethodFn("GET"),
20827
+ getConfig,
20828
+ head: makeMethodFn("HEAD"),
20829
+ interceptors,
20830
+ options: makeMethodFn("OPTIONS"),
20831
+ patch: makeMethodFn("PATCH"),
20832
+ post: makeMethodFn("POST"),
20833
+ put: makeMethodFn("PUT"),
20834
+ request,
20835
+ setConfig,
20836
+ sse: {
20837
+ connect: makeSseFn("CONNECT"),
20838
+ delete: makeSseFn("DELETE"),
20839
+ get: makeSseFn("GET"),
20840
+ head: makeSseFn("HEAD"),
20841
+ options: makeSseFn("OPTIONS"),
20842
+ patch: makeSseFn("PATCH"),
20843
+ post: makeSseFn("POST"),
20844
+ put: makeSseFn("PUT"),
20845
+ trace: makeSseFn("TRACE")
20846
+ },
20847
+ trace: makeMethodFn("TRACE")
20848
+ };
20849
+ };
20850
+ var init_client_gen15 = __esm(() => {
20851
+ init_utils_gen15();
20852
+ init_utils_gen16();
20853
+ });
20854
+
20855
+ // src/generated/seerr/client/index.ts
20856
+ var init_client9 = __esm(() => {
20857
+ init_client_gen15();
20858
+ init_utils_gen16();
20859
+ });
20860
+
20861
+ // src/generated/seerr/client.gen.ts
20862
+ var client8;
20863
+ var init_client_gen16 = __esm(() => {
20864
+ init_client9();
20865
+ client8 = createClient8(createConfig8());
20866
+ });
20867
+
20868
+ // src/generated/seerr/sdk.gen.ts
20869
+ var getStatus = (options) => (options?.client ?? client8).get({ url: "/status", ...options }), getUser = (options) => (options?.client ?? client8).get({
20870
+ security: [{
20871
+ in: "cookie",
20872
+ name: "connect.sid",
20873
+ type: "apiKey"
20874
+ }, { name: "X-Api-Key", type: "apiKey" }],
20875
+ url: "/user",
20876
+ ...options
20877
+ }), getUserByUserId = (options) => (options.client ?? client8).get({
20878
+ security: [{
20879
+ in: "cookie",
20880
+ name: "connect.sid",
20881
+ type: "apiKey"
20882
+ }, { name: "X-Api-Key", type: "apiKey" }],
20883
+ url: "/user/{userId}",
20884
+ ...options
20885
+ }), getSearch = (options) => (options.client ?? client8).get({
20886
+ security: [{
20887
+ in: "cookie",
20888
+ name: "connect.sid",
20889
+ type: "apiKey"
20890
+ }, { name: "X-Api-Key", type: "apiKey" }],
20891
+ url: "/search",
20892
+ ...options
20893
+ }), getRequest = (options) => (options?.client ?? client8).get({
20894
+ security: [{
20895
+ in: "cookie",
20896
+ name: "connect.sid",
20897
+ type: "apiKey"
20898
+ }, { name: "X-Api-Key", type: "apiKey" }],
20899
+ url: "/request",
20900
+ ...options
20901
+ }), getRequestCount = (options) => (options?.client ?? client8).get({
20902
+ security: [{
20903
+ in: "cookie",
20904
+ name: "connect.sid",
20905
+ type: "apiKey"
20906
+ }, { name: "X-Api-Key", type: "apiKey" }],
20907
+ url: "/request/count",
20908
+ ...options
20909
+ }), getRequestByRequestId = (options) => (options.client ?? client8).get({
20910
+ security: [{
20911
+ in: "cookie",
20912
+ name: "connect.sid",
20913
+ type: "apiKey"
20914
+ }, { name: "X-Api-Key", type: "apiKey" }],
20915
+ url: "/request/{requestId}",
20916
+ ...options
20917
+ }), postRequestByRequestIdByStatus = (options) => (options.client ?? client8).post({
20918
+ security: [{
20919
+ in: "cookie",
20920
+ name: "connect.sid",
20921
+ type: "apiKey"
20922
+ }, { name: "X-Api-Key", type: "apiKey" }],
20923
+ url: "/request/{requestId}/{status}",
20924
+ ...options
20925
+ }), getMedia = (options) => (options?.client ?? client8).get({
20926
+ security: [{
20927
+ in: "cookie",
20928
+ name: "connect.sid",
20929
+ type: "apiKey"
20930
+ }, { name: "X-Api-Key", type: "apiKey" }],
20931
+ url: "/media",
20932
+ ...options
20933
+ });
20934
+ var init_sdk_gen8 = __esm(() => {
20935
+ init_client_gen16();
20936
+ });
20937
+
20938
+ // src/generated/seerr/index.ts
20939
+ var init_seerr = __esm(() => {
20940
+ init_sdk_gen8();
20941
+ });
20942
+
20943
+ // src/clients/seerr.ts
20944
+ var exports_seerr = {};
20945
+ __export(exports_seerr, {
20946
+ SeerrClient: () => SeerrClient
20947
+ });
20948
+
20949
+ class SeerrClient {
20950
+ clientConfig;
20951
+ constructor(config) {
20952
+ this.clientConfig = createServarrClient(config);
20953
+ client8.setConfig({
20954
+ baseUrl: `${this.clientConfig.getBaseUrl()}/api/v1`,
20955
+ headers: {
20956
+ "X-Api-Key": this.clientConfig.config.apiKey,
20957
+ ...this.clientConfig.config.headers ?? {}
20958
+ }
20959
+ });
20960
+ }
20961
+ async getSystemStatus() {
20962
+ return getStatus();
20963
+ }
20964
+ async getRequests(options) {
20965
+ const query = {};
20966
+ if (options?.take)
20967
+ query.take = options.take;
20968
+ if (options?.skip)
20969
+ query.skip = options.skip;
20970
+ if (options?.filter)
20971
+ query.filter = options.filter;
20972
+ if (options?.sort)
20973
+ query.sort = options.sort;
20974
+ if (options?.sortDirection)
20975
+ query.sortDirection = options.sortDirection;
20976
+ return getRequest(Object.keys(query).length > 0 ? { query } : {});
20977
+ }
20978
+ async getRequestById(requestId) {
20979
+ return getRequestByRequestId({ path: { requestId } });
20980
+ }
20981
+ async getRequestCount() {
20982
+ return getRequestCount();
20983
+ }
20984
+ async approveRequest(requestId) {
20985
+ const result = await postRequestByRequestIdByStatus({
20986
+ path: { requestId, status: "approve" }
20987
+ });
20988
+ return result.data;
20989
+ }
20990
+ async declineRequest(requestId) {
20991
+ const result = await postRequestByRequestIdByStatus({
20992
+ path: { requestId, status: "decline" }
20993
+ });
20994
+ return result.data;
20995
+ }
20996
+ async search(query, page, language) {
20997
+ const searchQuery = { query };
20998
+ if (page)
20999
+ searchQuery.page = page;
21000
+ if (language)
21001
+ searchQuery.language = language;
21002
+ return getSearch({ query: searchQuery });
21003
+ }
21004
+ async getUsers(options) {
21005
+ const query = {};
21006
+ if (options?.take)
21007
+ query.take = options.take;
21008
+ if (options?.skip)
21009
+ query.skip = options.skip;
21010
+ if (options?.sort)
21011
+ query.sort = options.sort;
21012
+ return getUser(Object.keys(query).length > 0 ? { query } : {});
21013
+ }
21014
+ async getUserById(userId) {
21015
+ return getUserByUserId({ path: { userId } });
21016
+ }
21017
+ async getMedia(options) {
21018
+ const query = {};
21019
+ if (options?.take)
21020
+ query.take = options.take;
21021
+ if (options?.skip)
21022
+ query.skip = options.skip;
21023
+ return getMedia(Object.keys(query).length > 0 ? { query } : {});
21024
+ }
21025
+ updateConfig(newConfig) {
21026
+ const updatedConfig = { ...this.clientConfig.config, ...newConfig };
21027
+ this.clientConfig = createServarrClient(updatedConfig);
21028
+ client8.setConfig({
21029
+ baseUrl: `${this.clientConfig.getBaseUrl()}/api/v1`,
21030
+ headers: {
21031
+ "X-Api-Key": this.clientConfig.config.apiKey,
21032
+ ...this.clientConfig.config.headers ?? {}
21033
+ }
21034
+ });
21035
+ return this.clientConfig.config;
21036
+ }
21037
+ }
21038
+ var init_seerr2 = __esm(() => {
21039
+ init_client();
21040
+ init_client_gen16();
21041
+ init_seerr();
21042
+ });
21043
+
21044
+ // src/cli/commands/seerr.ts
21045
+ var exports_seerr3 = {};
21046
+ __export(exports_seerr3, {
21047
+ seerr: () => seerr,
21048
+ resources: () => resources8
21049
+ });
21050
+ var resources8, seerr;
21051
+ var init_seerr3 = __esm(() => {
21052
+ init_seerr2();
21053
+ init_service();
21054
+ resources8 = [
21055
+ {
21056
+ name: "requests",
21057
+ description: "Manage media requests",
21058
+ actions: [
21059
+ {
21060
+ name: "list",
21061
+ description: "List media requests",
21062
+ args: [
21063
+ {
21064
+ name: "filter",
21065
+ description: "Filter (all|approved|available|pending|processing|unavailable|failed|deleted|completed)"
21066
+ }
21067
+ ],
21068
+ columns: ["id", "status", "requestedBy", "createdAt", "updatedAt"],
21069
+ idField: "id",
21070
+ run: (c3, a2) => c3.getRequests(a2.filter ? { filter: a2.filter } : undefined)
21071
+ },
21072
+ {
21073
+ name: "count",
21074
+ description: "Get request counts",
21075
+ run: (c3) => c3.getRequestCount()
21076
+ },
21077
+ {
21078
+ name: "approve",
21079
+ description: "Approve a request",
21080
+ args: [
21081
+ {
21082
+ name: "id",
21083
+ description: "Request ID",
21084
+ required: true
21085
+ }
21086
+ ],
21087
+ run: (c3, a2) => c3.approveRequest(a2.id)
21088
+ },
21089
+ {
21090
+ name: "decline",
21091
+ description: "Decline a request",
21092
+ args: [
21093
+ {
21094
+ name: "id",
21095
+ description: "Request ID",
21096
+ required: true
21097
+ }
21098
+ ],
21099
+ confirmMessage: "Are you sure you want to decline this request?",
21100
+ run: (c3, a2) => c3.declineRequest(a2.id)
21101
+ }
21102
+ ]
21103
+ },
21104
+ {
21105
+ name: "search",
21106
+ description: "Search media",
21107
+ actions: [
21108
+ {
21109
+ name: "query",
21110
+ description: "Search for movies and TV shows",
21111
+ args: [
21112
+ {
21113
+ name: "query",
21114
+ description: "Search query",
21115
+ required: true
21116
+ }
21117
+ ],
21118
+ columns: ["id", "mediaType", "title", "releaseDate", "voteAverage"],
21119
+ idField: "id",
21120
+ run: (c3, a2) => c3.search(a2.query)
21121
+ }
21122
+ ]
21123
+ },
21124
+ {
21125
+ name: "users",
21126
+ description: "Manage users",
21127
+ actions: [
21128
+ {
21129
+ name: "list",
21130
+ description: "List users",
21131
+ columns: ["id", "email", "username", "requestCount", "createdAt"],
21132
+ idField: "id",
21133
+ run: (c3) => c3.getUsers()
21134
+ }
21135
+ ]
21136
+ },
21137
+ {
21138
+ name: "status",
21139
+ description: "Server status",
21140
+ actions: [
21141
+ {
21142
+ name: "show",
21143
+ description: "Show server status",
21144
+ columns: ["version", "commitTag", "updateAvailable", "commitsBehind"],
21145
+ run: (c3) => c3.getSystemStatus()
21146
+ }
21147
+ ]
21148
+ }
21149
+ ];
21150
+ seerr = buildServiceCommand("seerr", "Manage Seerr (Media Requests)", (config) => new SeerrClient(config), resources8);
21151
+ });
21152
+
21153
+ // src/cli/commands/doctor.ts
21154
+ var exports_doctor = {};
21155
+ __export(exports_doctor, {
21156
+ doctor: () => doctor
21157
+ });
21158
+ function classifyError(error) {
21159
+ if (!(error instanceof Error))
21160
+ return "Unknown error";
21161
+ const msg = error.message;
21162
+ const cause = error.cause;
21163
+ if (cause?.code === "ECONNREFUSED" || msg.includes("ECONNREFUSED")) {
21164
+ return "Connection refused - is the service running?";
21165
+ }
21166
+ if (cause?.code === "ENOTFOUND" || msg.includes("ENOTFOUND")) {
21167
+ return "Host not found - check the URL";
21168
+ }
21169
+ if (cause?.code === "ECONNRESET" || msg.includes("ECONNRESET")) {
21170
+ return "Connection reset - service may have crashed";
21171
+ }
21172
+ if (cause?.code === "ETIMEDOUT" || msg.includes("ETIMEDOUT") || msg.includes("timed out")) {
21173
+ return "Connection timed out - service may be unreachable";
21174
+ }
21175
+ if (msg.includes("fetch failed") || msg.includes("Failed to fetch")) {
21176
+ return `Service unreachable - ${cause?.message ?? "check URL and network"}`;
21177
+ }
21178
+ if (msg.includes("401") || msg.includes("Unauthorized")) {
21179
+ return "Authentication failed (401) - check your API key";
21180
+ }
21181
+ if (msg.includes("403") || msg.includes("Forbidden")) {
21182
+ return "Access denied (403) - check your API key permissions";
21183
+ }
21184
+ if (msg.includes("502") || msg.includes("Bad Gateway")) {
21185
+ return "Bad gateway (502) - reverse proxy or service issue";
21186
+ }
21187
+ if (msg.includes("503") || msg.includes("Service Unavailable")) {
21188
+ return "Service unavailable (503) - service may be starting up";
21189
+ }
21190
+ if (msg.includes("CERT") || msg.includes("certificate") || msg.includes("SSL")) {
21191
+ return "SSL/TLS certificate error - check HTTPS configuration";
21192
+ }
21193
+ return msg;
21194
+ }
21195
+ function extractVersion(service, status) {
21196
+ const data = status?.data ?? status;
21197
+ if (typeof data === "string") {
21198
+ return null;
21199
+ }
21200
+ if (service === "bazarr") {
21201
+ return data?.data?.bazarr_version ?? data?.bazarr_version ?? null;
21202
+ }
21203
+ if (service === "qbittorrent" || service === "seerr") {
21204
+ return data?.version ?? null;
21205
+ }
21206
+ return data?.version ?? status?.version ?? null;
21207
+ }
21208
+ var clientFactories, doctor;
21209
+ var init_doctor = __esm(() => {
21210
+ init_dist();
21211
+ init_dist2();
21212
+ init_bazarr2();
21213
+ init_lidarr2();
21214
+ init_prowlarr2();
21215
+ init_qbittorrent2();
21216
+ init_radarr2();
21217
+ init_readarr2();
21218
+ init_seerr2();
21219
+ init_sonarr2();
21220
+ init_config();
21221
+ init_output();
21222
+ clientFactories = {
21223
+ radarr: (c3) => new RadarrClient(c3),
21224
+ sonarr: (c3) => new SonarrClient(c3),
21225
+ lidarr: (c3) => new LidarrClient(c3),
21226
+ readarr: (c3) => new ReadarrClient(c3),
21227
+ prowlarr: (c3) => new ProwlarrClient(c3),
21228
+ bazarr: (c3) => new BazarrClient(c3),
21229
+ qbittorrent: (c3) => new QBittorrentClient(c3),
21230
+ seerr: (c3) => new SeerrClient(c3)
21231
+ };
21232
+ doctor = defineCommand({
21233
+ meta: {
21234
+ name: "doctor",
21235
+ description: "Test all configured service connections"
21236
+ },
21237
+ args: {
21238
+ json: { type: "boolean", description: "Output as JSON" },
21239
+ table: { type: "boolean", description: "Output as table" },
21240
+ plain: { type: "boolean", description: "Output as TSV (no colors, for piping)" },
21241
+ quiet: { type: "boolean", alias: "q", description: "Output service names only" },
21242
+ select: { type: "string", description: "Cherry-pick fields (comma-separated, JSON mode)" }
21243
+ },
21244
+ async run({ args }) {
21245
+ const format = detectFormat(args);
21246
+ let hasAny = false;
21247
+ const results = [];
21248
+ if (format === "table") {
21249
+ consola.info(`Checking connections...
21250
+ `);
21251
+ }
21252
+ for (const service of SERVICES) {
21253
+ const svcConfig = getServiceConfig(service);
21254
+ if (!svcConfig) {
21255
+ results.push({
21256
+ service,
21257
+ configured: false,
21258
+ status: "not configured"
21259
+ });
21260
+ continue;
21261
+ }
21262
+ hasAny = true;
21263
+ try {
21264
+ const factory = clientFactories[service];
21265
+ if (!factory) {
21266
+ results.push({
21267
+ service,
21268
+ configured: true,
21269
+ status: "fail",
21270
+ baseUrl: svcConfig.baseUrl,
21271
+ error: "No client factory available"
21272
+ });
21273
+ continue;
21274
+ }
21275
+ const client9 = factory(svcConfig);
21276
+ const status = await client9.getSystemStatus();
21277
+ const version = extractVersion(service, status) ?? "?";
21278
+ if (version === "?") {
21279
+ throw new Error("Unexpected response payload");
21280
+ }
21281
+ results.push({
21282
+ service,
21283
+ configured: true,
21284
+ status: "ok",
21285
+ version: String(version),
21286
+ baseUrl: svcConfig.baseUrl
21287
+ });
21288
+ } catch (error) {
21289
+ results.push({
21290
+ service,
21291
+ configured: true,
21292
+ status: "fail",
21293
+ baseUrl: svcConfig.baseUrl,
21294
+ error: classifyError(error)
21295
+ });
21296
+ }
21297
+ }
21298
+ const hadFailure = !hasAny || results.some((r3) => r3.status === "fail");
21299
+ if (!hasAny && format === "table") {
21300
+ consola.warn("\nNo services configured. Run `tsarr config init` to set up.");
21301
+ }
21302
+ formatOutput(results, {
21303
+ format,
21304
+ columns: ["service", "status", "version", "baseUrl", "error"],
21305
+ idField: "service",
21306
+ select: args.select
21307
+ });
21308
+ if (hadFailure) {
21309
+ process.exitCode = 1;
21310
+ }
21311
+ }
21312
+ });
21313
+ });
21314
+
21315
+ // src/cli/commands/config.ts
21316
+ var exports_config = {};
21317
+ __export(exports_config, {
21318
+ config: () => config
21319
+ });
21320
+ var DEFAULT_PORTS, configInit, configSet, configGet, configShow, config;
21321
+ var init_config2 = __esm(() => {
21322
+ init_dist();
21323
+ init_dist2();
21324
+ init_config();
21325
+ init_prompt2();
21326
+ DEFAULT_PORTS = {
21327
+ radarr: 7878,
21328
+ sonarr: 8989,
21329
+ lidarr: 8686,
21330
+ readarr: 8787,
21331
+ prowlarr: 9696,
21332
+ bazarr: 6767,
21333
+ qbittorrent: 8080,
21334
+ seerr: 5055
21335
+ };
21336
+ configInit = defineCommand({
21337
+ meta: {
21338
+ name: "init",
21339
+ description: "Interactive setup wizard"
21340
+ },
21341
+ async run() {
21342
+ if (!process.stdin.isTTY) {
21343
+ consola.error("Config init requires an interactive terminal.\nUse `tsarr config set` or environment variables for non-interactive setup.");
21344
+ process.exit(1);
21345
+ }
21346
+ consola.info(`Welcome to TsArr CLI setup!
18982
21347
  `);
18983
21348
  const selected = await promptMultiSelect("Which services do you want to configure?", SERVICES.map((s2) => ({
18984
21349
  label: `${s2} (default port: ${DEFAULT_PORTS[s2]})`,
@@ -18992,32 +21357,47 @@ var init_config2 = __esm(() => {
18992
21357
  for (const service of selected) {
18993
21358
  console.log();
18994
21359
  const baseUrl = await promptIfMissing(undefined, `${service} base URL (e.g. http://localhost:${DEFAULT_PORTS[service]})`);
18995
- const apiKey = await promptIfMissing(undefined, `${service} API key`);
18996
- config.services[service] = { baseUrl, apiKey };
18997
- const svcConfig = { baseUrl, apiKey };
18998
- try {
18999
- const { RadarrClient: RadarrClient2 } = await Promise.resolve().then(() => (init_radarr2(), exports_radarr));
19000
- const { SonarrClient: SonarrClient2 } = await Promise.resolve().then(() => (init_sonarr2(), exports_sonarr));
19001
- const { LidarrClient: LidarrClient2 } = await Promise.resolve().then(() => (init_lidarr2(), exports_lidarr));
19002
- const { ReadarrClient: ReadarrClient2 } = await Promise.resolve().then(() => (init_readarr2(), exports_readarr));
19003
- const { ProwlarrClient: ProwlarrClient2 } = await Promise.resolve().then(() => (init_prowlarr2(), exports_prowlarr));
19004
- const { BazarrClient: BazarrClient2 } = await Promise.resolve().then(() => (init_bazarr2(), exports_bazarr));
19005
- const factories = {
19006
- radarr: (c3) => new RadarrClient2(c3),
19007
- sonarr: (c3) => new SonarrClient2(c3),
19008
- lidarr: (c3) => new LidarrClient2(c3),
19009
- readarr: (c3) => new ReadarrClient2(c3),
19010
- prowlarr: (c3) => new ProwlarrClient2(c3),
19011
- bazarr: (c3) => new BazarrClient2(c3)
19012
- };
19013
- const client7 = factories[service]?.(svcConfig);
19014
- if (client7) {
19015
- const status = await client7.getSystemStatus();
19016
- const version = status?.data?.version ?? status?.version ?? "?";
19017
- consola.success(`Connected to ${service} v${version}`);
21360
+ if (service === "qbittorrent") {
21361
+ const username = await promptIfMissing(undefined, `${service} username`);
21362
+ const password = await promptIfMissing(undefined, `${service} password`);
21363
+ config.services[service] = { baseUrl, username, password };
21364
+ try {
21365
+ const { QBittorrentClient: QBittorrentClient2 } = await Promise.resolve().then(() => (init_qbittorrent2(), exports_qbittorrent));
21366
+ const client9 = new QBittorrentClient2({ baseUrl, username, password });
21367
+ const status = await client9.getSystemStatus();
21368
+ consola.success(`Connected to ${service} v${status.version}`);
21369
+ } catch {
21370
+ consola.warn(`Could not connect to ${service} — config saved anyway.`);
21371
+ }
21372
+ } else {
21373
+ const apiKey = await promptIfMissing(undefined, `${service} API key`);
21374
+ config.services[service] = { baseUrl, apiKey };
21375
+ try {
21376
+ const { RadarrClient: RadarrClient2 } = await Promise.resolve().then(() => (init_radarr2(), exports_radarr));
21377
+ const { SonarrClient: SonarrClient2 } = await Promise.resolve().then(() => (init_sonarr2(), exports_sonarr));
21378
+ const { LidarrClient: LidarrClient2 } = await Promise.resolve().then(() => (init_lidarr2(), exports_lidarr));
21379
+ const { ReadarrClient: ReadarrClient2 } = await Promise.resolve().then(() => (init_readarr2(), exports_readarr));
21380
+ const { ProwlarrClient: ProwlarrClient2 } = await Promise.resolve().then(() => (init_prowlarr2(), exports_prowlarr));
21381
+ const { BazarrClient: BazarrClient2 } = await Promise.resolve().then(() => (init_bazarr2(), exports_bazarr));
21382
+ const { SeerrClient: SeerrClient2 } = await Promise.resolve().then(() => (init_seerr2(), exports_seerr));
21383
+ const factories = {
21384
+ radarr: (c3) => new RadarrClient2(c3),
21385
+ sonarr: (c3) => new SonarrClient2(c3),
21386
+ lidarr: (c3) => new LidarrClient2(c3),
21387
+ readarr: (c3) => new ReadarrClient2(c3),
21388
+ prowlarr: (c3) => new ProwlarrClient2(c3),
21389
+ bazarr: (c3) => new BazarrClient2(c3),
21390
+ seerr: (c3) => new SeerrClient2(c3)
21391
+ };
21392
+ const client9 = factories[service]?.(config.services[service]);
21393
+ if (client9) {
21394
+ const status = await client9.getSystemStatus();
21395
+ const version = status?.data?.version ?? status?.version ?? "?";
21396
+ consola.success(`Connected to ${service} v${version}`);
21397
+ }
21398
+ } catch {
21399
+ consola.warn(`Could not connect to ${service} — config saved anyway.`);
19018
21400
  }
19019
- } catch {
19020
- consola.warn(`Could not connect to ${service} — config saved anyway.`);
19021
21401
  }
19022
21402
  }
19023
21403
  const location = await promptSelect("Save config to:", [
@@ -19084,6 +21464,8 @@ var init_config2 = __esm(() => {
19084
21464
  for (const svc of Object.values(redacted.services)) {
19085
21465
  if (svc?.apiKey)
19086
21466
  svc.apiKey = "*****";
21467
+ if (svc?.password)
21468
+ svc.password = "*****";
19087
21469
  }
19088
21470
  }
19089
21471
  console.log(JSON.stringify(redacted, null, 2));
@@ -19111,11 +21493,11 @@ __export(exports_completions, {
19111
21493
  function generateBashCompletion() {
19112
21494
  const services = Object.keys(SERVICE_COMMANDS).join(" ");
19113
21495
  const globals = "doctor config completions";
19114
- const resourceVars = Object.entries(SERVICE_COMMANDS).map(([svc, resources7]) => ` local ${svc}_resources="${Object.keys(resources7).join(" ")}"`).join(`
21496
+ const resourceVars = Object.entries(SERVICE_COMMANDS).map(([svc, resources9]) => ` local ${svc}_resources="${Object.keys(resources9).join(" ")}"`).join(`
19115
21497
  `);
19116
21498
  const resourceCases = Object.keys(SERVICE_COMMANDS).map((svc) => ` ${svc}) COMPREPLY=( $(compgen -W "$${svc}_resources" -- "$cur") ) ;;`).join(`
19117
21499
  `);
19118
- const actionCases = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources7]) => Object.entries(resources7).map(([res, actions]) => ` ${res}) [[ "\${COMP_WORDS[1]}" == "${svc}" ]] && COMPREPLY=( $(compgen -W "${actions.join(" ")}" -- "$cur") ) ;;`)).join(`
21500
+ const actionCases = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources9]) => Object.entries(resources9).map(([res, actions]) => ` ${res}) [[ "\${COMP_WORDS[1]}" == "${svc}" ]] && COMPREPLY=( $(compgen -W "${actions.join(" ")}" -- "$cur") ) ;;`)).join(`
19119
21501
  `);
19120
21502
  return `#!/bin/bash
19121
21503
  _tsarr_completions() {
@@ -19149,9 +21531,9 @@ complete -F _tsarr_completions tsarr`;
19149
21531
  }
19150
21532
  function generateZshCompletion() {
19151
21533
  const services = Object.keys(SERVICE_COMMANDS).join(" ");
19152
- const resourceAssoc = Object.entries(SERVICE_COMMANDS).map(([svc, resources7]) => ` ${svc} "${Object.keys(resources7).join(" ")}"`).join(`
21534
+ const resourceAssoc = Object.entries(SERVICE_COMMANDS).map(([svc, resources9]) => ` ${svc} "${Object.keys(resources9).join(" ")}"`).join(`
19153
21535
  `);
19154
- const actionAssoc = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources7]) => Object.entries(resources7).map(([res, actions]) => ` ${svc}:${res} "${actions.join(" ")}"`)).join(`
21536
+ const actionAssoc = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources9]) => Object.entries(resources9).map(([res, actions]) => ` ${svc}:${res} "${actions.join(" ")}"`)).join(`
19155
21537
  `);
19156
21538
  return `#compdef tsarr
19157
21539
 
@@ -19208,12 +21590,12 @@ _tsarr "$@"`;
19208
21590
  function generateFishCompletion() {
19209
21591
  const services = Object.keys(SERVICE_COMMANDS).join(" ");
19210
21592
  const globals = "doctor config completions";
19211
- const resourceCompletions = Object.entries(SERVICE_COMMANDS).map(([svc, resources7]) => {
19212
- const res = Object.keys(resources7).join(" ");
21593
+ const resourceCompletions = Object.entries(SERVICE_COMMANDS).map(([svc, resources9]) => {
21594
+ const res = Object.keys(resources9).join(" ");
19213
21595
  return `complete -c tsarr -n "__fish_seen_subcommand_from ${svc}; and not __fish_seen_subcommand_from ${res}" -a "${res}"`;
19214
21596
  }).join(`
19215
21597
  `);
19216
- const actionCompletions = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources7]) => Object.entries(resources7).map(([res, actions]) => `complete -c tsarr -n "__fish_seen_subcommand_from ${svc}; and __fish_seen_subcommand_from ${res}; and not __fish_seen_subcommand_from ${actions.join(" ")}" -a "${actions.join(" ")}"`)).join(`
21598
+ const actionCompletions = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources9]) => Object.entries(resources9).map(([res, actions]) => `complete -c tsarr -n "__fish_seen_subcommand_from ${svc}; and __fish_seen_subcommand_from ${res}; and not __fish_seen_subcommand_from ${actions.join(" ")}" -a "${actions.join(" ")}"`)).join(`
19217
21599
  `);
19218
21600
  return `# Fish completions for tsarr
19219
21601
  set -l services ${services}
@@ -19290,6 +21672,12 @@ var init_completions = __esm(() => {
19290
21672
  provider: ["list"],
19291
21673
  language: ["list", "profiles"],
19292
21674
  system: ["status", "health", "badges"]
21675
+ },
21676
+ seerr: {
21677
+ requests: ["list", "count", "approve", "decline"],
21678
+ search: ["query"],
21679
+ users: ["list"],
21680
+ status: ["show"]
19293
21681
  }
19294
21682
  };
19295
21683
  completions = defineCommand({
@@ -19328,7 +21716,7 @@ init_dist();
19328
21716
  // package.json
19329
21717
  var package_default = {
19330
21718
  name: "tsarr",
19331
- version: "2.5.0",
21719
+ version: "2.7.0",
19332
21720
  author: "Robbe Verhelst",
19333
21721
  repository: {
19334
21722
  type: "git",
@@ -19340,16 +21728,16 @@ var package_default = {
19340
21728
  main: "dist/index.js",
19341
21729
  module: "dist/index.js",
19342
21730
  devDependencies: {
19343
- "@biomejs/biome": "2.4.10",
19344
- "@hey-api/openapi-ts": "^0.94.5",
21731
+ "@biomejs/biome": "2.4.11",
21732
+ "@hey-api/openapi-ts": "^0.96.0",
19345
21733
  "@semantic-release/changelog": "^6.0.3",
19346
21734
  "@semantic-release/git": "^10.0.1",
19347
21735
  "@semantic-release/github": "^12.0.6",
19348
21736
  "@semantic-release/npm": "^13.1.5",
19349
- "@types/bun": "^1.3.11",
21737
+ "@types/bun": "^1.3.12",
19350
21738
  "semantic-release": "^25.0.3",
19351
- typedoc: "^0.28.18",
19352
- typescript: "^5.9.3"
21739
+ typedoc: "^0.28.19",
21740
+ typescript: "^6.0.2"
19353
21741
  },
19354
21742
  exports: {
19355
21743
  ".": {
@@ -19380,6 +21768,14 @@ var package_default = {
19380
21768
  import: "./dist/clients/bazarr.js",
19381
21769
  types: "./dist/clients/bazarr.d.ts"
19382
21770
  },
21771
+ "./qbittorrent": {
21772
+ import: "./dist/clients/qbittorrent.js",
21773
+ types: "./dist/clients/qbittorrent.d.ts"
21774
+ },
21775
+ "./seerr": {
21776
+ import: "./dist/clients/seerr.js",
21777
+ types: "./dist/clients/seerr.d.ts"
21778
+ },
19383
21779
  "./radarr/types": {
19384
21780
  types: "./dist/clients/radarr-types.d.ts"
19385
21781
  },
@@ -19397,6 +21793,12 @@ var package_default = {
19397
21793
  },
19398
21794
  "./bazarr/types": {
19399
21795
  types: "./dist/clients/bazarr-types.d.ts"
21796
+ },
21797
+ "./qbittorrent/types": {
21798
+ types: "./dist/clients/qbittorrent-types.d.ts"
21799
+ },
21800
+ "./seerr/types": {
21801
+ types: "./dist/clients/seerr-types.d.ts"
19400
21802
  }
19401
21803
  },
19402
21804
  description: "Type-safe TypeScript SDK for Servarr APIs (Radarr, Sonarr, etc.)",
@@ -19415,6 +21817,10 @@ var package_default = {
19415
21817
  "readarr",
19416
21818
  "prowlarr",
19417
21819
  "bazarr",
21820
+ "qbittorrent",
21821
+ "seerr",
21822
+ "jellyseerr",
21823
+ "overseerr",
19418
21824
  "typescript",
19419
21825
  "sdk",
19420
21826
  "api",
@@ -19428,7 +21834,7 @@ var package_default = {
19428
21834
  },
19429
21835
  scripts: {
19430
21836
  build: "bun run generate && bun run generate:types && bun run build:js && bun run build:cli && bun run build:types",
19431
- "build:js": "bun build src/index.ts --outdir dist --target node --minify --splitting && bun build src/clients/radarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/sonarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/lidarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/readarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/prowlarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/bazarr.ts --outdir dist/clients --target node --format esm",
21837
+ "build:js": "bun build src/index.ts --outdir dist --target node --minify --splitting && bun build src/clients/radarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/sonarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/lidarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/readarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/prowlarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/bazarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/qbittorrent.ts --outdir dist/clients --target node --format esm && bun build src/clients/seerr.ts --outdir dist/clients --target node --format esm",
19432
21838
  "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target node --format esm && chmod +x dist/cli/index.js",
19433
21839
  "build:types": "tsc --project tsconfig.build.json",
19434
21840
  prepublishOnly: "bun run build",
@@ -19455,7 +21861,7 @@ var package_default = {
19455
21861
  type: "module",
19456
21862
  types: "dist/index.d.ts",
19457
21863
  dependencies: {
19458
- citty: "^0.2.1",
21864
+ citty: "^0.2.2",
19459
21865
  consola: "^3.4.2"
19460
21866
  }
19461
21867
  };
@@ -19466,7 +21872,7 @@ var main = defineCommand({
19466
21872
  meta: {
19467
21873
  name: "tsarr",
19468
21874
  version,
19469
- description: "Type-safe CLI for Servarr APIs (Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr)"
21875
+ description: "Type-safe CLI for Servarr APIs (Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr, qBittorrent, Seerr)"
19470
21876
  },
19471
21877
  subCommands: {
19472
21878
  radarr: () => Promise.resolve().then(() => (init_radarr3(), exports_radarr3)).then((m2) => m2.radarr),
@@ -19475,6 +21881,8 @@ var main = defineCommand({
19475
21881
  readarr: () => Promise.resolve().then(() => (init_readarr3(), exports_readarr3)).then((m2) => m2.readarr),
19476
21882
  prowlarr: () => Promise.resolve().then(() => (init_prowlarr3(), exports_prowlarr3)).then((m2) => m2.prowlarr),
19477
21883
  bazarr: () => Promise.resolve().then(() => (init_bazarr3(), exports_bazarr3)).then((m2) => m2.bazarr),
21884
+ qbit: () => Promise.resolve().then(() => (init_qbit(), exports_qbit)).then((m2) => m2.qbit),
21885
+ seerr: () => Promise.resolve().then(() => (init_seerr3(), exports_seerr3)).then((m2) => m2.seerr),
19478
21886
  doctor: () => Promise.resolve().then(() => (init_doctor(), exports_doctor)).then((m2) => m2.doctor),
19479
21887
  config: () => Promise.resolve().then(() => (init_config2(), exports_config)).then((m2) => m2.config),
19480
21888
  completions: () => Promise.resolve().then(() => (init_completions(), exports_completions)).then((m2) => m2.completions)