tsarr 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/qbit.d.ts +4 -0
- package/dist/cli/commands/qbit.d.ts.map +1 -0
- package/dist/cli/commands/service.d.ts +1 -2
- package/dist/cli/commands/service.d.ts.map +1 -1
- package/dist/cli/config.d.ts +6 -4
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/index.js +1601 -301
- package/dist/clients/bazarr.js +7 -7
- package/dist/clients/lidarr.js +7 -7
- package/dist/clients/prowlarr.js +7 -7
- package/dist/clients/qbittorrent-types.d.ts +2 -0
- package/dist/clients/qbittorrent-types.d.ts.map +1 -0
- package/dist/clients/qbittorrent.d.ts +40 -0
- package/dist/clients/qbittorrent.d.ts.map +1 -0
- package/dist/clients/qbittorrent.js +1011 -0
- package/dist/clients/radarr.js +7 -7
- package/dist/clients/readarr.js +7 -7
- package/dist/clients/sonarr.js +7 -7
- package/dist/core/types.d.ts +6 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/generated/bazarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/bazarr/client/types.gen.d.ts +1 -1
- package/dist/generated/bazarr/core/serverSentEvents.gen.d.ts +1 -1
- package/dist/generated/bazarr/core/serverSentEvents.gen.d.ts.map +1 -1
- package/dist/generated/bazarr/sdk.gen.d.ts +1 -1
- package/dist/generated/bazarr/sdk.gen.d.ts.map +1 -1
- package/dist/generated/lidarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/lidarr/client/types.gen.d.ts +1 -1
- package/dist/generated/lidarr/core/serverSentEvents.gen.d.ts +1 -1
- package/dist/generated/lidarr/core/serverSentEvents.gen.d.ts.map +1 -1
- package/dist/generated/lidarr/sdk.gen.d.ts +1 -1
- package/dist/generated/lidarr/sdk.gen.d.ts.map +1 -1
- package/dist/generated/prowlarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/prowlarr/client/types.gen.d.ts +1 -1
- package/dist/generated/prowlarr/core/serverSentEvents.gen.d.ts +1 -1
- package/dist/generated/prowlarr/core/serverSentEvents.gen.d.ts.map +1 -1
- package/dist/generated/prowlarr/sdk.gen.d.ts +1 -1
- package/dist/generated/prowlarr/sdk.gen.d.ts.map +1 -1
- package/dist/generated/qbittorrent/client/client.gen.d.ts +3 -0
- package/dist/generated/qbittorrent/client/client.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/client/index.d.ts +9 -0
- package/dist/generated/qbittorrent/client/index.d.ts.map +1 -0
- package/dist/generated/qbittorrent/client/types.gen.d.ts +118 -0
- package/dist/generated/qbittorrent/client/types.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/client/utils.gen.d.ts +34 -0
- package/dist/generated/qbittorrent/client/utils.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/client.gen.d.ts +13 -0
- package/dist/generated/qbittorrent/client.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/auth.gen.d.ts +19 -0
- package/dist/generated/qbittorrent/core/auth.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/bodySerializer.gen.d.ts +26 -0
- package/dist/generated/qbittorrent/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/params.gen.d.ts +44 -0
- package/dist/generated/qbittorrent/core/params.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/pathSerializer.gen.d.ts +34 -0
- package/dist/generated/qbittorrent/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/generated/qbittorrent/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/generated/qbittorrent/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/types.gen.d.ts +79 -0
- package/dist/generated/qbittorrent/core/types.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/core/utils.gen.d.ts +20 -0
- package/dist/generated/qbittorrent/core/utils.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/index.d.ts +3 -0
- package/dist/generated/qbittorrent/index.d.ts.map +1 -0
- package/dist/generated/qbittorrent/sdk.gen.d.ts +453 -0
- package/dist/generated/qbittorrent/sdk.gen.d.ts.map +1 -0
- package/dist/generated/qbittorrent/types.gen.d.ts +3689 -0
- package/dist/generated/qbittorrent/types.gen.d.ts.map +1 -0
- package/dist/generated/radarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/radarr/client/types.gen.d.ts +1 -1
- package/dist/generated/radarr/core/serverSentEvents.gen.d.ts +1 -1
- package/dist/generated/radarr/core/serverSentEvents.gen.d.ts.map +1 -1
- package/dist/generated/radarr/sdk.gen.d.ts +1 -1
- package/dist/generated/radarr/sdk.gen.d.ts.map +1 -1
- package/dist/generated/readarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/readarr/client/types.gen.d.ts +1 -1
- package/dist/generated/readarr/core/serverSentEvents.gen.d.ts +1 -1
- package/dist/generated/readarr/core/serverSentEvents.gen.d.ts.map +1 -1
- package/dist/generated/readarr/sdk.gen.d.ts +1 -1
- package/dist/generated/readarr/sdk.gen.d.ts.map +1 -1
- package/dist/generated/sonarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/sonarr/client/types.gen.d.ts +1 -1
- package/dist/generated/sonarr/core/serverSentEvents.gen.d.ts +1 -1
- package/dist/generated/sonarr/core/serverSentEvents.gen.d.ts.map +1 -1
- package/dist/generated/sonarr/sdk.gen.d.ts +1 -1
- package/dist/generated/sonarr/sdk.gen.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -31
- package/dist/tsarr-2.6.0.tgz +0 -0
- package/package.json +16 -8
- 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
|
-
|
|
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
|
-
|
|
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
|
|
287
|
-
const
|
|
288
|
-
if (
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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
|
-
}
|
|
300
|
-
|
|
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.
|
|
362
|
+
const subCommandArgIndex = findSubCommandIndex(rawArgs, await resolveValue(cmd.args || {}));
|
|
309
363
|
const subCommandName = rawArgs[subCommandArgIndex];
|
|
310
|
-
const subCommand = await
|
|
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
|
-
|
|
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
|
|
347
|
-
argLines.push([cyan(argStr
|
|
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
|
|
438
|
+
argLines.push([cyan(negativeArgStr), [arg.negativeDescription, isRequired ? gray("(Required)") : ""].filter(Boolean).join(" ")]);
|
|
351
439
|
}
|
|
352
440
|
if (isRequired)
|
|
353
|
-
usageLine.push(
|
|
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
|
-
|
|
363
|
-
|
|
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
|
-
|
|
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]
|
|
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
|
-
|
|
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
|
|
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
|
|
1105
|
-
|
|
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 (
|
|
4770
|
-
|
|
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,15 @@ 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 = [
|
|
5076
|
+
SERVICES = [
|
|
5077
|
+
"radarr",
|
|
5078
|
+
"sonarr",
|
|
5079
|
+
"lidarr",
|
|
5080
|
+
"readarr",
|
|
5081
|
+
"prowlarr",
|
|
5082
|
+
"bazarr",
|
|
5083
|
+
"qbittorrent"
|
|
5084
|
+
];
|
|
4926
5085
|
GLOBAL_CONFIG_DIR = join(homedir(), ".config", "tsarr");
|
|
4927
5086
|
GLOBAL_CONFIG_PATH = join(GLOBAL_CONFIG_DIR, "config.json");
|
|
4928
5087
|
});
|
|
@@ -5199,7 +5358,8 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
|
|
|
5199
5358
|
async run({ args }) {
|
|
5200
5359
|
const config = getServiceConfig(serviceName);
|
|
5201
5360
|
if (!config) {
|
|
5202
|
-
|
|
5361
|
+
const envHint = serviceName === "qbittorrent" ? `TSARR_QBITTORRENT_URL, TSARR_QBITTORRENT_USERNAME, and TSARR_QBITTORRENT_PASSWORD` : `TSARR_${serviceName.toUpperCase()}_URL and TSARR_${serviceName.toUpperCase()}_API_KEY`;
|
|
5362
|
+
consola.error(`${serviceName} is not configured. Run \`tsarr config init\` or set ${envHint} environment variables.`);
|
|
5203
5363
|
process.exit(1);
|
|
5204
5364
|
}
|
|
5205
5365
|
try {
|
|
@@ -5241,8 +5401,9 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
|
|
|
5241
5401
|
const err = raw.error;
|
|
5242
5402
|
const status = err?.status ?? raw?.response?.status;
|
|
5243
5403
|
if (status === 401) {
|
|
5244
|
-
|
|
5245
|
-
Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY
|
|
5404
|
+
const authHint = serviceName === "qbittorrent" ? "Check your username and password." : `Check your API key.
|
|
5405
|
+
Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY`;
|
|
5406
|
+
consola.error(`Unauthorized. ${authHint}`);
|
|
5246
5407
|
} else if (status === 404) {
|
|
5247
5408
|
consola.error("Not found.");
|
|
5248
5409
|
} else {
|
|
@@ -5304,6 +5465,8 @@ function isWriteAction(actionName) {
|
|
|
5304
5465
|
"create",
|
|
5305
5466
|
"delete",
|
|
5306
5467
|
"edit",
|
|
5468
|
+
"pause",
|
|
5469
|
+
"resume",
|
|
5307
5470
|
"refresh",
|
|
5308
5471
|
"manual-search",
|
|
5309
5472
|
"grab",
|
|
@@ -5991,7 +6154,7 @@ var init_bodySerializer_gen2 = __esm(() => {
|
|
|
5991
6154
|
});
|
|
5992
6155
|
|
|
5993
6156
|
// src/generated/sonarr/core/serverSentEvents.gen.ts
|
|
5994
|
-
|
|
6157
|
+
function createSseClient2({
|
|
5995
6158
|
onRequest,
|
|
5996
6159
|
onSseError,
|
|
5997
6160
|
onSseEvent,
|
|
@@ -6003,7 +6166,7 @@ var createSseClient2 = ({
|
|
|
6003
6166
|
sseSleepFn,
|
|
6004
6167
|
url,
|
|
6005
6168
|
...options
|
|
6006
|
-
})
|
|
6169
|
+
}) {
|
|
6007
6170
|
let lastEventId;
|
|
6008
6171
|
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
6009
6172
|
const createStream = async function* () {
|
|
@@ -6050,8 +6213,7 @@ var createSseClient2 = ({
|
|
|
6050
6213
|
if (done)
|
|
6051
6214
|
break;
|
|
6052
6215
|
buffer += value;
|
|
6053
|
-
buffer = buffer.replace(/\r\n
|
|
6054
|
-
`).replace(/\r/g, `
|
|
6216
|
+
buffer = buffer.replace(/\r\n?/g, `
|
|
6055
6217
|
`);
|
|
6056
6218
|
const chunks = buffer.split(`
|
|
6057
6219
|
|
|
@@ -6124,7 +6286,7 @@ var createSseClient2 = ({
|
|
|
6124
6286
|
};
|
|
6125
6287
|
const stream = createStream();
|
|
6126
6288
|
return { stream };
|
|
6127
|
-
}
|
|
6289
|
+
}
|
|
6128
6290
|
|
|
6129
6291
|
// src/generated/sonarr/core/pathSerializer.gen.ts
|
|
6130
6292
|
var separatorArrayExplode2 = (style) => {
|
|
@@ -6589,8 +6751,9 @@ var createClient2 = (config = {}) => {
|
|
|
6589
6751
|
if (opts.body === undefined || opts.serializedBody === "") {
|
|
6590
6752
|
opts.headers.delete("Content-Type");
|
|
6591
6753
|
}
|
|
6592
|
-
const
|
|
6593
|
-
|
|
6754
|
+
const resolvedOpts = opts;
|
|
6755
|
+
const url = buildUrl2(resolvedOpts);
|
|
6756
|
+
return { opts: resolvedOpts, url };
|
|
6594
6757
|
};
|
|
6595
6758
|
const request = async (options) => {
|
|
6596
6759
|
const { opts, url } = await beforeRequest(options);
|
|
@@ -9166,7 +9329,7 @@ var init_bodySerializer_gen3 = __esm(() => {
|
|
|
9166
9329
|
});
|
|
9167
9330
|
|
|
9168
9331
|
// src/generated/lidarr/core/serverSentEvents.gen.ts
|
|
9169
|
-
|
|
9332
|
+
function createSseClient3({
|
|
9170
9333
|
onRequest,
|
|
9171
9334
|
onSseError,
|
|
9172
9335
|
onSseEvent,
|
|
@@ -9178,7 +9341,7 @@ var createSseClient3 = ({
|
|
|
9178
9341
|
sseSleepFn,
|
|
9179
9342
|
url,
|
|
9180
9343
|
...options
|
|
9181
|
-
})
|
|
9344
|
+
}) {
|
|
9182
9345
|
let lastEventId;
|
|
9183
9346
|
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
9184
9347
|
const createStream = async function* () {
|
|
@@ -9225,8 +9388,7 @@ var createSseClient3 = ({
|
|
|
9225
9388
|
if (done)
|
|
9226
9389
|
break;
|
|
9227
9390
|
buffer += value;
|
|
9228
|
-
buffer = buffer.replace(/\r\n
|
|
9229
|
-
`).replace(/\r/g, `
|
|
9391
|
+
buffer = buffer.replace(/\r\n?/g, `
|
|
9230
9392
|
`);
|
|
9231
9393
|
const chunks = buffer.split(`
|
|
9232
9394
|
|
|
@@ -9299,7 +9461,7 @@ var createSseClient3 = ({
|
|
|
9299
9461
|
};
|
|
9300
9462
|
const stream = createStream();
|
|
9301
9463
|
return { stream };
|
|
9302
|
-
}
|
|
9464
|
+
}
|
|
9303
9465
|
|
|
9304
9466
|
// src/generated/lidarr/core/pathSerializer.gen.ts
|
|
9305
9467
|
var separatorArrayExplode3 = (style) => {
|
|
@@ -9764,8 +9926,9 @@ var createClient3 = (config = {}) => {
|
|
|
9764
9926
|
if (opts.body === undefined || opts.serializedBody === "") {
|
|
9765
9927
|
opts.headers.delete("Content-Type");
|
|
9766
9928
|
}
|
|
9767
|
-
const
|
|
9768
|
-
|
|
9929
|
+
const resolvedOpts = opts;
|
|
9930
|
+
const url = buildUrl3(resolvedOpts);
|
|
9931
|
+
return { opts: resolvedOpts, url };
|
|
9769
9932
|
};
|
|
9770
9933
|
const request = async (options) => {
|
|
9771
9934
|
const { opts, url } = await beforeRequest(options);
|
|
@@ -12220,7 +12383,7 @@ var init_bodySerializer_gen4 = __esm(() => {
|
|
|
12220
12383
|
});
|
|
12221
12384
|
|
|
12222
12385
|
// src/generated/readarr/core/serverSentEvents.gen.ts
|
|
12223
|
-
|
|
12386
|
+
function createSseClient4({
|
|
12224
12387
|
onRequest,
|
|
12225
12388
|
onSseError,
|
|
12226
12389
|
onSseEvent,
|
|
@@ -12232,7 +12395,7 @@ var createSseClient4 = ({
|
|
|
12232
12395
|
sseSleepFn,
|
|
12233
12396
|
url,
|
|
12234
12397
|
...options
|
|
12235
|
-
})
|
|
12398
|
+
}) {
|
|
12236
12399
|
let lastEventId;
|
|
12237
12400
|
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
12238
12401
|
const createStream = async function* () {
|
|
@@ -12279,8 +12442,7 @@ var createSseClient4 = ({
|
|
|
12279
12442
|
if (done)
|
|
12280
12443
|
break;
|
|
12281
12444
|
buffer += value;
|
|
12282
|
-
buffer = buffer.replace(/\r\n
|
|
12283
|
-
`).replace(/\r/g, `
|
|
12445
|
+
buffer = buffer.replace(/\r\n?/g, `
|
|
12284
12446
|
`);
|
|
12285
12447
|
const chunks = buffer.split(`
|
|
12286
12448
|
|
|
@@ -12353,7 +12515,7 @@ var createSseClient4 = ({
|
|
|
12353
12515
|
};
|
|
12354
12516
|
const stream = createStream();
|
|
12355
12517
|
return { stream };
|
|
12356
|
-
}
|
|
12518
|
+
}
|
|
12357
12519
|
|
|
12358
12520
|
// src/generated/readarr/core/pathSerializer.gen.ts
|
|
12359
12521
|
var separatorArrayExplode4 = (style) => {
|
|
@@ -12818,8 +12980,9 @@ var createClient4 = (config = {}) => {
|
|
|
12818
12980
|
if (opts.body === undefined || opts.serializedBody === "") {
|
|
12819
12981
|
opts.headers.delete("Content-Type");
|
|
12820
12982
|
}
|
|
12821
|
-
const
|
|
12822
|
-
|
|
12983
|
+
const resolvedOpts = opts;
|
|
12984
|
+
const url = buildUrl4(resolvedOpts);
|
|
12985
|
+
return { opts: resolvedOpts, url };
|
|
12823
12986
|
};
|
|
12824
12987
|
const request = async (options) => {
|
|
12825
12988
|
const { opts, url } = await beforeRequest(options);
|
|
@@ -15255,7 +15418,7 @@ var init_bodySerializer_gen5 = __esm(() => {
|
|
|
15255
15418
|
});
|
|
15256
15419
|
|
|
15257
15420
|
// src/generated/prowlarr/core/serverSentEvents.gen.ts
|
|
15258
|
-
|
|
15421
|
+
function createSseClient5({
|
|
15259
15422
|
onRequest,
|
|
15260
15423
|
onSseError,
|
|
15261
15424
|
onSseEvent,
|
|
@@ -15267,7 +15430,7 @@ var createSseClient5 = ({
|
|
|
15267
15430
|
sseSleepFn,
|
|
15268
15431
|
url,
|
|
15269
15432
|
...options
|
|
15270
|
-
})
|
|
15433
|
+
}) {
|
|
15271
15434
|
let lastEventId;
|
|
15272
15435
|
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
15273
15436
|
const createStream = async function* () {
|
|
@@ -15314,8 +15477,7 @@ var createSseClient5 = ({
|
|
|
15314
15477
|
if (done)
|
|
15315
15478
|
break;
|
|
15316
15479
|
buffer += value;
|
|
15317
|
-
buffer = buffer.replace(/\r\n
|
|
15318
|
-
`).replace(/\r/g, `
|
|
15480
|
+
buffer = buffer.replace(/\r\n?/g, `
|
|
15319
15481
|
`);
|
|
15320
15482
|
const chunks = buffer.split(`
|
|
15321
15483
|
|
|
@@ -15388,7 +15550,7 @@ var createSseClient5 = ({
|
|
|
15388
15550
|
};
|
|
15389
15551
|
const stream = createStream();
|
|
15390
15552
|
return { stream };
|
|
15391
|
-
}
|
|
15553
|
+
}
|
|
15392
15554
|
|
|
15393
15555
|
// src/generated/prowlarr/core/pathSerializer.gen.ts
|
|
15394
15556
|
var separatorArrayExplode5 = (style) => {
|
|
@@ -15853,8 +16015,9 @@ var createClient5 = (config = {}) => {
|
|
|
15853
16015
|
if (opts.body === undefined || opts.serializedBody === "") {
|
|
15854
16016
|
opts.headers.delete("Content-Type");
|
|
15855
16017
|
}
|
|
15856
|
-
const
|
|
15857
|
-
|
|
16018
|
+
const resolvedOpts = opts;
|
|
16019
|
+
const url = buildUrl5(resolvedOpts);
|
|
16020
|
+
return { opts: resolvedOpts, url };
|
|
15858
16021
|
};
|
|
15859
16022
|
const request = async (options) => {
|
|
15860
16023
|
const { opts, url } = await beforeRequest(options);
|
|
@@ -17254,7 +17417,7 @@ var init_bodySerializer_gen6 = __esm(() => {
|
|
|
17254
17417
|
});
|
|
17255
17418
|
|
|
17256
17419
|
// src/generated/bazarr/core/serverSentEvents.gen.ts
|
|
17257
|
-
|
|
17420
|
+
function createSseClient6({
|
|
17258
17421
|
onRequest,
|
|
17259
17422
|
onSseError,
|
|
17260
17423
|
onSseEvent,
|
|
@@ -17266,7 +17429,7 @@ var createSseClient6 = ({
|
|
|
17266
17429
|
sseSleepFn,
|
|
17267
17430
|
url,
|
|
17268
17431
|
...options
|
|
17269
|
-
})
|
|
17432
|
+
}) {
|
|
17270
17433
|
let lastEventId;
|
|
17271
17434
|
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
17272
17435
|
const createStream = async function* () {
|
|
@@ -17313,8 +17476,7 @@ var createSseClient6 = ({
|
|
|
17313
17476
|
if (done)
|
|
17314
17477
|
break;
|
|
17315
17478
|
buffer += value;
|
|
17316
|
-
buffer = buffer.replace(/\r\n
|
|
17317
|
-
`).replace(/\r/g, `
|
|
17479
|
+
buffer = buffer.replace(/\r\n?/g, `
|
|
17318
17480
|
`);
|
|
17319
17481
|
const chunks = buffer.split(`
|
|
17320
17482
|
|
|
@@ -17387,7 +17549,7 @@ var createSseClient6 = ({
|
|
|
17387
17549
|
};
|
|
17388
17550
|
const stream = createStream();
|
|
17389
17551
|
return { stream };
|
|
17390
|
-
}
|
|
17552
|
+
}
|
|
17391
17553
|
|
|
17392
17554
|
// src/generated/bazarr/core/pathSerializer.gen.ts
|
|
17393
17555
|
var separatorArrayExplode6 = (style) => {
|
|
@@ -17852,8 +18014,9 @@ var createClient6 = (config = {}) => {
|
|
|
17852
18014
|
if (opts.body === undefined || opts.serializedBody === "") {
|
|
17853
18015
|
opts.headers.delete("Content-Type");
|
|
17854
18016
|
}
|
|
17855
|
-
const
|
|
17856
|
-
|
|
18017
|
+
const resolvedOpts = opts;
|
|
18018
|
+
const url = buildUrl6(resolvedOpts);
|
|
18019
|
+
return { opts: resolvedOpts, url };
|
|
17857
18020
|
};
|
|
17858
18021
|
const request = async (options) => {
|
|
17859
18022
|
const { opts, url } = await beforeRequest(options);
|
|
@@ -18794,191 +18957,1304 @@ var init_bazarr3 = __esm(() => {
|
|
|
18794
18957
|
bazarr = buildServiceCommand("bazarr", "Manage Bazarr (Subtitles)", (config) => new BazarrClient(config), resources6);
|
|
18795
18958
|
});
|
|
18796
18959
|
|
|
18797
|
-
// src/
|
|
18798
|
-
var
|
|
18799
|
-
|
|
18800
|
-
|
|
18801
|
-
}
|
|
18802
|
-
|
|
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;
|
|
18960
|
+
// src/generated/qbittorrent/core/bodySerializer.gen.ts
|
|
18961
|
+
var serializeUrlSearchParamsPair = (data, key, value) => {
|
|
18962
|
+
if (typeof value === "string") {
|
|
18963
|
+
data.append(key, value);
|
|
18964
|
+
} else {
|
|
18965
|
+
data.append(key, JSON.stringify(value));
|
|
18846
18966
|
}
|
|
18847
|
-
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
|
|
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)
|
|
18967
|
+
}, jsonBodySerializer7, urlSearchParamsBodySerializer2;
|
|
18968
|
+
var init_bodySerializer_gen7 = __esm(() => {
|
|
18969
|
+
jsonBodySerializer7 = {
|
|
18970
|
+
bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
|
|
18868
18971
|
};
|
|
18869
|
-
|
|
18870
|
-
|
|
18871
|
-
|
|
18872
|
-
|
|
18873
|
-
|
|
18874
|
-
|
|
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;
|
|
18972
|
+
urlSearchParamsBodySerializer2 = {
|
|
18973
|
+
bodySerializer: (body) => {
|
|
18974
|
+
const data = new URLSearchParams;
|
|
18975
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
18976
|
+
if (value === undefined || value === null) {
|
|
18977
|
+
return;
|
|
18898
18978
|
}
|
|
18899
|
-
|
|
18900
|
-
|
|
18901
|
-
|
|
18902
|
-
|
|
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
|
-
});
|
|
18979
|
+
if (Array.isArray(value)) {
|
|
18980
|
+
value.forEach((v2) => serializeUrlSearchParamsPair(data, key, v2));
|
|
18981
|
+
} else {
|
|
18982
|
+
serializeUrlSearchParamsPair(data, key, value);
|
|
18933
18983
|
}
|
|
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
18984
|
});
|
|
18945
|
-
|
|
18946
|
-
process.exitCode = 1;
|
|
18947
|
-
}
|
|
18985
|
+
return data.toString();
|
|
18948
18986
|
}
|
|
18949
|
-
}
|
|
18987
|
+
};
|
|
18950
18988
|
});
|
|
18951
18989
|
|
|
18952
|
-
// src/
|
|
18953
|
-
|
|
18954
|
-
|
|
18955
|
-
|
|
18956
|
-
|
|
18957
|
-
|
|
18958
|
-
|
|
18959
|
-
|
|
18960
|
-
|
|
18961
|
-
|
|
18962
|
-
|
|
18963
|
-
|
|
18964
|
-
|
|
18965
|
-
|
|
18966
|
-
|
|
18967
|
-
|
|
18968
|
-
|
|
18969
|
-
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
if (
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
18981
|
-
|
|
18990
|
+
// src/generated/qbittorrent/core/serverSentEvents.gen.ts
|
|
18991
|
+
function createSseClient7({
|
|
18992
|
+
onRequest,
|
|
18993
|
+
onSseError,
|
|
18994
|
+
onSseEvent,
|
|
18995
|
+
responseTransformer,
|
|
18996
|
+
responseValidator,
|
|
18997
|
+
sseDefaultRetryDelay,
|
|
18998
|
+
sseMaxRetryAttempts,
|
|
18999
|
+
sseMaxRetryDelay,
|
|
19000
|
+
sseSleepFn,
|
|
19001
|
+
url,
|
|
19002
|
+
...options
|
|
19003
|
+
}) {
|
|
19004
|
+
let lastEventId;
|
|
19005
|
+
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
19006
|
+
const createStream = async function* () {
|
|
19007
|
+
let retryDelay = sseDefaultRetryDelay ?? 3000;
|
|
19008
|
+
let attempt = 0;
|
|
19009
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
19010
|
+
while (true) {
|
|
19011
|
+
if (signal.aborted)
|
|
19012
|
+
break;
|
|
19013
|
+
attempt++;
|
|
19014
|
+
const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
|
|
19015
|
+
if (lastEventId !== undefined) {
|
|
19016
|
+
headers.set("Last-Event-ID", lastEventId);
|
|
19017
|
+
}
|
|
19018
|
+
try {
|
|
19019
|
+
const requestInit = {
|
|
19020
|
+
redirect: "follow",
|
|
19021
|
+
...options,
|
|
19022
|
+
body: options.serializedBody,
|
|
19023
|
+
headers,
|
|
19024
|
+
signal
|
|
19025
|
+
};
|
|
19026
|
+
let request = new Request(url, requestInit);
|
|
19027
|
+
if (onRequest) {
|
|
19028
|
+
request = await onRequest(url, requestInit);
|
|
19029
|
+
}
|
|
19030
|
+
const _fetch = options.fetch ?? globalThis.fetch;
|
|
19031
|
+
const response = await _fetch(request);
|
|
19032
|
+
if (!response.ok)
|
|
19033
|
+
throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
|
|
19034
|
+
if (!response.body)
|
|
19035
|
+
throw new Error("No body in SSE response");
|
|
19036
|
+
const reader = response.body.pipeThrough(new TextDecoderStream).getReader();
|
|
19037
|
+
let buffer = "";
|
|
19038
|
+
const abortHandler = () => {
|
|
19039
|
+
try {
|
|
19040
|
+
reader.cancel();
|
|
19041
|
+
} catch {}
|
|
19042
|
+
};
|
|
19043
|
+
signal.addEventListener("abort", abortHandler);
|
|
19044
|
+
try {
|
|
19045
|
+
while (true) {
|
|
19046
|
+
const { done, value } = await reader.read();
|
|
19047
|
+
if (done)
|
|
19048
|
+
break;
|
|
19049
|
+
buffer += value;
|
|
19050
|
+
buffer = buffer.replace(/\r\n?/g, `
|
|
19051
|
+
`);
|
|
19052
|
+
const chunks = buffer.split(`
|
|
19053
|
+
|
|
19054
|
+
`);
|
|
19055
|
+
buffer = chunks.pop() ?? "";
|
|
19056
|
+
for (const chunk of chunks) {
|
|
19057
|
+
const lines = chunk.split(`
|
|
19058
|
+
`);
|
|
19059
|
+
const dataLines = [];
|
|
19060
|
+
let eventName;
|
|
19061
|
+
for (const line of lines) {
|
|
19062
|
+
if (line.startsWith("data:")) {
|
|
19063
|
+
dataLines.push(line.replace(/^data:\s*/, ""));
|
|
19064
|
+
} else if (line.startsWith("event:")) {
|
|
19065
|
+
eventName = line.replace(/^event:\s*/, "");
|
|
19066
|
+
} else if (line.startsWith("id:")) {
|
|
19067
|
+
lastEventId = line.replace(/^id:\s*/, "");
|
|
19068
|
+
} else if (line.startsWith("retry:")) {
|
|
19069
|
+
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
|
|
19070
|
+
if (!Number.isNaN(parsed)) {
|
|
19071
|
+
retryDelay = parsed;
|
|
19072
|
+
}
|
|
19073
|
+
}
|
|
19074
|
+
}
|
|
19075
|
+
let data;
|
|
19076
|
+
let parsedJson = false;
|
|
19077
|
+
if (dataLines.length) {
|
|
19078
|
+
const rawData = dataLines.join(`
|
|
19079
|
+
`);
|
|
19080
|
+
try {
|
|
19081
|
+
data = JSON.parse(rawData);
|
|
19082
|
+
parsedJson = true;
|
|
19083
|
+
} catch {
|
|
19084
|
+
data = rawData;
|
|
19085
|
+
}
|
|
19086
|
+
}
|
|
19087
|
+
if (parsedJson) {
|
|
19088
|
+
if (responseValidator) {
|
|
19089
|
+
await responseValidator(data);
|
|
19090
|
+
}
|
|
19091
|
+
if (responseTransformer) {
|
|
19092
|
+
data = await responseTransformer(data);
|
|
19093
|
+
}
|
|
19094
|
+
}
|
|
19095
|
+
onSseEvent?.({
|
|
19096
|
+
data,
|
|
19097
|
+
event: eventName,
|
|
19098
|
+
id: lastEventId,
|
|
19099
|
+
retry: retryDelay
|
|
19100
|
+
});
|
|
19101
|
+
if (dataLines.length) {
|
|
19102
|
+
yield data;
|
|
19103
|
+
}
|
|
19104
|
+
}
|
|
19105
|
+
}
|
|
19106
|
+
} finally {
|
|
19107
|
+
signal.removeEventListener("abort", abortHandler);
|
|
19108
|
+
reader.releaseLock();
|
|
19109
|
+
}
|
|
19110
|
+
break;
|
|
19111
|
+
} catch (error) {
|
|
19112
|
+
onSseError?.(error);
|
|
19113
|
+
if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
|
|
19114
|
+
break;
|
|
19115
|
+
}
|
|
19116
|
+
const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
|
|
19117
|
+
await sleep(backoff);
|
|
19118
|
+
}
|
|
19119
|
+
}
|
|
19120
|
+
};
|
|
19121
|
+
const stream = createStream();
|
|
19122
|
+
return { stream };
|
|
19123
|
+
}
|
|
19124
|
+
|
|
19125
|
+
// src/generated/qbittorrent/core/pathSerializer.gen.ts
|
|
19126
|
+
var separatorArrayExplode7 = (style) => {
|
|
19127
|
+
switch (style) {
|
|
19128
|
+
case "label":
|
|
19129
|
+
return ".";
|
|
19130
|
+
case "matrix":
|
|
19131
|
+
return ";";
|
|
19132
|
+
case "simple":
|
|
19133
|
+
return ",";
|
|
19134
|
+
default:
|
|
19135
|
+
return "&";
|
|
19136
|
+
}
|
|
19137
|
+
}, separatorArrayNoExplode7 = (style) => {
|
|
19138
|
+
switch (style) {
|
|
19139
|
+
case "form":
|
|
19140
|
+
return ",";
|
|
19141
|
+
case "pipeDelimited":
|
|
19142
|
+
return "|";
|
|
19143
|
+
case "spaceDelimited":
|
|
19144
|
+
return "%20";
|
|
19145
|
+
default:
|
|
19146
|
+
return ",";
|
|
19147
|
+
}
|
|
19148
|
+
}, separatorObjectExplode7 = (style) => {
|
|
19149
|
+
switch (style) {
|
|
19150
|
+
case "label":
|
|
19151
|
+
return ".";
|
|
19152
|
+
case "matrix":
|
|
19153
|
+
return ";";
|
|
19154
|
+
case "simple":
|
|
19155
|
+
return ",";
|
|
19156
|
+
default:
|
|
19157
|
+
return "&";
|
|
19158
|
+
}
|
|
19159
|
+
}, serializeArrayParam7 = ({
|
|
19160
|
+
allowReserved,
|
|
19161
|
+
explode,
|
|
19162
|
+
name,
|
|
19163
|
+
style,
|
|
19164
|
+
value
|
|
19165
|
+
}) => {
|
|
19166
|
+
if (!explode) {
|
|
19167
|
+
const joinedValues2 = (allowReserved ? value : value.map((v2) => encodeURIComponent(v2))).join(separatorArrayNoExplode7(style));
|
|
19168
|
+
switch (style) {
|
|
19169
|
+
case "label":
|
|
19170
|
+
return `.${joinedValues2}`;
|
|
19171
|
+
case "matrix":
|
|
19172
|
+
return `;${name}=${joinedValues2}`;
|
|
19173
|
+
case "simple":
|
|
19174
|
+
return joinedValues2;
|
|
19175
|
+
default:
|
|
19176
|
+
return `${name}=${joinedValues2}`;
|
|
19177
|
+
}
|
|
19178
|
+
}
|
|
19179
|
+
const separator = separatorArrayExplode7(style);
|
|
19180
|
+
const joinedValues = value.map((v2) => {
|
|
19181
|
+
if (style === "label" || style === "simple") {
|
|
19182
|
+
return allowReserved ? v2 : encodeURIComponent(v2);
|
|
19183
|
+
}
|
|
19184
|
+
return serializePrimitiveParam7({
|
|
19185
|
+
allowReserved,
|
|
19186
|
+
name,
|
|
19187
|
+
value: v2
|
|
19188
|
+
});
|
|
19189
|
+
}).join(separator);
|
|
19190
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
19191
|
+
}, serializePrimitiveParam7 = ({
|
|
19192
|
+
allowReserved,
|
|
19193
|
+
name,
|
|
19194
|
+
value
|
|
19195
|
+
}) => {
|
|
19196
|
+
if (value === undefined || value === null) {
|
|
19197
|
+
return "";
|
|
19198
|
+
}
|
|
19199
|
+
if (typeof value === "object") {
|
|
19200
|
+
throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
|
|
19201
|
+
}
|
|
19202
|
+
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
19203
|
+
}, serializeObjectParam7 = ({
|
|
19204
|
+
allowReserved,
|
|
19205
|
+
explode,
|
|
19206
|
+
name,
|
|
19207
|
+
style,
|
|
19208
|
+
value,
|
|
19209
|
+
valueOnly
|
|
19210
|
+
}) => {
|
|
19211
|
+
if (value instanceof Date) {
|
|
19212
|
+
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
|
19213
|
+
}
|
|
19214
|
+
if (style !== "deepObject" && !explode) {
|
|
19215
|
+
let values = [];
|
|
19216
|
+
Object.entries(value).forEach(([key, v2]) => {
|
|
19217
|
+
values = [...values, key, allowReserved ? v2 : encodeURIComponent(v2)];
|
|
19218
|
+
});
|
|
19219
|
+
const joinedValues2 = values.join(",");
|
|
19220
|
+
switch (style) {
|
|
19221
|
+
case "form":
|
|
19222
|
+
return `${name}=${joinedValues2}`;
|
|
19223
|
+
case "label":
|
|
19224
|
+
return `.${joinedValues2}`;
|
|
19225
|
+
case "matrix":
|
|
19226
|
+
return `;${name}=${joinedValues2}`;
|
|
19227
|
+
default:
|
|
19228
|
+
return joinedValues2;
|
|
19229
|
+
}
|
|
19230
|
+
}
|
|
19231
|
+
const separator = separatorObjectExplode7(style);
|
|
19232
|
+
const joinedValues = Object.entries(value).map(([key, v2]) => serializePrimitiveParam7({
|
|
19233
|
+
allowReserved,
|
|
19234
|
+
name: style === "deepObject" ? `${name}[${key}]` : key,
|
|
19235
|
+
value: v2
|
|
19236
|
+
})).join(separator);
|
|
19237
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
19238
|
+
};
|
|
19239
|
+
|
|
19240
|
+
// src/generated/qbittorrent/core/utils.gen.ts
|
|
19241
|
+
function getValidRequestBody7(options) {
|
|
19242
|
+
const hasBody = options.body !== undefined;
|
|
19243
|
+
const isSerializedBody = hasBody && options.bodySerializer;
|
|
19244
|
+
if (isSerializedBody) {
|
|
19245
|
+
if ("serializedBody" in options) {
|
|
19246
|
+
const hasSerializedBody = options.serializedBody !== undefined && options.serializedBody !== "";
|
|
19247
|
+
return hasSerializedBody ? options.serializedBody : null;
|
|
19248
|
+
}
|
|
19249
|
+
return options.body !== "" ? options.body : null;
|
|
19250
|
+
}
|
|
19251
|
+
if (hasBody) {
|
|
19252
|
+
return options.body;
|
|
19253
|
+
}
|
|
19254
|
+
return;
|
|
19255
|
+
}
|
|
19256
|
+
var PATH_PARAM_RE7, defaultPathSerializer7 = ({ path, url: _url }) => {
|
|
19257
|
+
let url = _url;
|
|
19258
|
+
const matches = _url.match(PATH_PARAM_RE7);
|
|
19259
|
+
if (matches) {
|
|
19260
|
+
for (const match of matches) {
|
|
19261
|
+
let explode = false;
|
|
19262
|
+
let name = match.substring(1, match.length - 1);
|
|
19263
|
+
let style = "simple";
|
|
19264
|
+
if (name.endsWith("*")) {
|
|
19265
|
+
explode = true;
|
|
19266
|
+
name = name.substring(0, name.length - 1);
|
|
19267
|
+
}
|
|
19268
|
+
if (name.startsWith(".")) {
|
|
19269
|
+
name = name.substring(1);
|
|
19270
|
+
style = "label";
|
|
19271
|
+
} else if (name.startsWith(";")) {
|
|
19272
|
+
name = name.substring(1);
|
|
19273
|
+
style = "matrix";
|
|
19274
|
+
}
|
|
19275
|
+
const value = path[name];
|
|
19276
|
+
if (value === undefined || value === null) {
|
|
19277
|
+
continue;
|
|
19278
|
+
}
|
|
19279
|
+
if (Array.isArray(value)) {
|
|
19280
|
+
url = url.replace(match, serializeArrayParam7({ explode, name, style, value }));
|
|
19281
|
+
continue;
|
|
19282
|
+
}
|
|
19283
|
+
if (typeof value === "object") {
|
|
19284
|
+
url = url.replace(match, serializeObjectParam7({
|
|
19285
|
+
explode,
|
|
19286
|
+
name,
|
|
19287
|
+
style,
|
|
19288
|
+
value,
|
|
19289
|
+
valueOnly: true
|
|
19290
|
+
}));
|
|
19291
|
+
continue;
|
|
19292
|
+
}
|
|
19293
|
+
if (style === "matrix") {
|
|
19294
|
+
url = url.replace(match, `;${serializePrimitiveParam7({
|
|
19295
|
+
name,
|
|
19296
|
+
value
|
|
19297
|
+
})}`);
|
|
19298
|
+
continue;
|
|
19299
|
+
}
|
|
19300
|
+
const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
|
|
19301
|
+
url = url.replace(match, replaceValue);
|
|
19302
|
+
}
|
|
19303
|
+
}
|
|
19304
|
+
return url;
|
|
19305
|
+
}, getUrl7 = ({
|
|
19306
|
+
baseUrl,
|
|
19307
|
+
path,
|
|
19308
|
+
query,
|
|
19309
|
+
querySerializer,
|
|
19310
|
+
url: _url
|
|
19311
|
+
}) => {
|
|
19312
|
+
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
19313
|
+
let url = (baseUrl ?? "") + pathUrl;
|
|
19314
|
+
if (path) {
|
|
19315
|
+
url = defaultPathSerializer7({ path, url });
|
|
19316
|
+
}
|
|
19317
|
+
let search = query ? querySerializer(query) : "";
|
|
19318
|
+
if (search.startsWith("?")) {
|
|
19319
|
+
search = search.substring(1);
|
|
19320
|
+
}
|
|
19321
|
+
if (search) {
|
|
19322
|
+
url += `?${search}`;
|
|
19323
|
+
}
|
|
19324
|
+
return url;
|
|
19325
|
+
};
|
|
19326
|
+
var init_utils_gen13 = __esm(() => {
|
|
19327
|
+
PATH_PARAM_RE7 = /\{[^{}]+\}/g;
|
|
19328
|
+
});
|
|
19329
|
+
|
|
19330
|
+
// src/generated/qbittorrent/core/auth.gen.ts
|
|
19331
|
+
var getAuthToken7 = async (auth, callback) => {
|
|
19332
|
+
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
19333
|
+
if (!token) {
|
|
19334
|
+
return;
|
|
19335
|
+
}
|
|
19336
|
+
if (auth.scheme === "bearer") {
|
|
19337
|
+
return `Bearer ${token}`;
|
|
19338
|
+
}
|
|
19339
|
+
if (auth.scheme === "basic") {
|
|
19340
|
+
return `Basic ${btoa(token)}`;
|
|
19341
|
+
}
|
|
19342
|
+
return token;
|
|
19343
|
+
};
|
|
19344
|
+
|
|
19345
|
+
// src/generated/qbittorrent/client/utils.gen.ts
|
|
19346
|
+
class Interceptors7 {
|
|
19347
|
+
fns = [];
|
|
19348
|
+
clear() {
|
|
19349
|
+
this.fns = [];
|
|
19350
|
+
}
|
|
19351
|
+
eject(id) {
|
|
19352
|
+
const index = this.getInterceptorIndex(id);
|
|
19353
|
+
if (this.fns[index]) {
|
|
19354
|
+
this.fns[index] = null;
|
|
19355
|
+
}
|
|
19356
|
+
}
|
|
19357
|
+
exists(id) {
|
|
19358
|
+
const index = this.getInterceptorIndex(id);
|
|
19359
|
+
return Boolean(this.fns[index]);
|
|
19360
|
+
}
|
|
19361
|
+
getInterceptorIndex(id) {
|
|
19362
|
+
if (typeof id === "number") {
|
|
19363
|
+
return this.fns[id] ? id : -1;
|
|
19364
|
+
}
|
|
19365
|
+
return this.fns.indexOf(id);
|
|
19366
|
+
}
|
|
19367
|
+
update(id, fn) {
|
|
19368
|
+
const index = this.getInterceptorIndex(id);
|
|
19369
|
+
if (this.fns[index]) {
|
|
19370
|
+
this.fns[index] = fn;
|
|
19371
|
+
return id;
|
|
19372
|
+
}
|
|
19373
|
+
return false;
|
|
19374
|
+
}
|
|
19375
|
+
use(fn) {
|
|
19376
|
+
this.fns.push(fn);
|
|
19377
|
+
return this.fns.length - 1;
|
|
19378
|
+
}
|
|
19379
|
+
}
|
|
19380
|
+
var createQuerySerializer7 = ({
|
|
19381
|
+
parameters = {},
|
|
19382
|
+
...args
|
|
19383
|
+
} = {}) => {
|
|
19384
|
+
const querySerializer = (queryParams) => {
|
|
19385
|
+
const search = [];
|
|
19386
|
+
if (queryParams && typeof queryParams === "object") {
|
|
19387
|
+
for (const name in queryParams) {
|
|
19388
|
+
const value = queryParams[name];
|
|
19389
|
+
if (value === undefined || value === null) {
|
|
19390
|
+
continue;
|
|
19391
|
+
}
|
|
19392
|
+
const options = parameters[name] || args;
|
|
19393
|
+
if (Array.isArray(value)) {
|
|
19394
|
+
const serializedArray = serializeArrayParam7({
|
|
19395
|
+
allowReserved: options.allowReserved,
|
|
19396
|
+
explode: true,
|
|
19397
|
+
name,
|
|
19398
|
+
style: "form",
|
|
19399
|
+
value,
|
|
19400
|
+
...options.array
|
|
19401
|
+
});
|
|
19402
|
+
if (serializedArray)
|
|
19403
|
+
search.push(serializedArray);
|
|
19404
|
+
} else if (typeof value === "object") {
|
|
19405
|
+
const serializedObject = serializeObjectParam7({
|
|
19406
|
+
allowReserved: options.allowReserved,
|
|
19407
|
+
explode: true,
|
|
19408
|
+
name,
|
|
19409
|
+
style: "deepObject",
|
|
19410
|
+
value,
|
|
19411
|
+
...options.object
|
|
19412
|
+
});
|
|
19413
|
+
if (serializedObject)
|
|
19414
|
+
search.push(serializedObject);
|
|
19415
|
+
} else {
|
|
19416
|
+
const serializedPrimitive = serializePrimitiveParam7({
|
|
19417
|
+
allowReserved: options.allowReserved,
|
|
19418
|
+
name,
|
|
19419
|
+
value
|
|
19420
|
+
});
|
|
19421
|
+
if (serializedPrimitive)
|
|
19422
|
+
search.push(serializedPrimitive);
|
|
19423
|
+
}
|
|
19424
|
+
}
|
|
19425
|
+
}
|
|
19426
|
+
return search.join("&");
|
|
19427
|
+
};
|
|
19428
|
+
return querySerializer;
|
|
19429
|
+
}, getParseAs7 = (contentType) => {
|
|
19430
|
+
if (!contentType) {
|
|
19431
|
+
return "stream";
|
|
19432
|
+
}
|
|
19433
|
+
const cleanContent = contentType.split(";")[0]?.trim();
|
|
19434
|
+
if (!cleanContent) {
|
|
19435
|
+
return;
|
|
19436
|
+
}
|
|
19437
|
+
if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
|
|
19438
|
+
return "json";
|
|
19439
|
+
}
|
|
19440
|
+
if (cleanContent === "multipart/form-data") {
|
|
19441
|
+
return "formData";
|
|
19442
|
+
}
|
|
19443
|
+
if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
|
|
19444
|
+
return "blob";
|
|
19445
|
+
}
|
|
19446
|
+
if (cleanContent.startsWith("text/")) {
|
|
19447
|
+
return "text";
|
|
19448
|
+
}
|
|
19449
|
+
return;
|
|
19450
|
+
}, checkForExistence7 = (options, name) => {
|
|
19451
|
+
if (!name) {
|
|
19452
|
+
return false;
|
|
19453
|
+
}
|
|
19454
|
+
if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
|
|
19455
|
+
return true;
|
|
19456
|
+
}
|
|
19457
|
+
return false;
|
|
19458
|
+
}, setAuthParams7 = async ({
|
|
19459
|
+
security,
|
|
19460
|
+
...options
|
|
19461
|
+
}) => {
|
|
19462
|
+
for (const auth of security) {
|
|
19463
|
+
if (checkForExistence7(options, auth.name)) {
|
|
19464
|
+
continue;
|
|
19465
|
+
}
|
|
19466
|
+
const token = await getAuthToken7(auth, options.auth);
|
|
19467
|
+
if (!token) {
|
|
19468
|
+
continue;
|
|
19469
|
+
}
|
|
19470
|
+
const name = auth.name ?? "Authorization";
|
|
19471
|
+
switch (auth.in) {
|
|
19472
|
+
case "query":
|
|
19473
|
+
if (!options.query) {
|
|
19474
|
+
options.query = {};
|
|
19475
|
+
}
|
|
19476
|
+
options.query[name] = token;
|
|
19477
|
+
break;
|
|
19478
|
+
case "cookie":
|
|
19479
|
+
options.headers.append("Cookie", `${name}=${token}`);
|
|
19480
|
+
break;
|
|
19481
|
+
case "header":
|
|
19482
|
+
default:
|
|
19483
|
+
options.headers.set(name, token);
|
|
19484
|
+
break;
|
|
19485
|
+
}
|
|
19486
|
+
}
|
|
19487
|
+
}, buildUrl7 = (options) => getUrl7({
|
|
19488
|
+
baseUrl: options.baseUrl,
|
|
19489
|
+
path: options.path,
|
|
19490
|
+
query: options.query,
|
|
19491
|
+
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer7(options.querySerializer),
|
|
19492
|
+
url: options.url
|
|
19493
|
+
}), mergeConfigs7 = (a2, b2) => {
|
|
19494
|
+
const config = { ...a2, ...b2 };
|
|
19495
|
+
if (config.baseUrl?.endsWith("/")) {
|
|
19496
|
+
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
|
19497
|
+
}
|
|
19498
|
+
config.headers = mergeHeaders7(a2.headers, b2.headers);
|
|
19499
|
+
return config;
|
|
19500
|
+
}, headersEntries7 = (headers) => {
|
|
19501
|
+
const entries = [];
|
|
19502
|
+
headers.forEach((value, key) => {
|
|
19503
|
+
entries.push([key, value]);
|
|
19504
|
+
});
|
|
19505
|
+
return entries;
|
|
19506
|
+
}, mergeHeaders7 = (...headers) => {
|
|
19507
|
+
const mergedHeaders = new Headers;
|
|
19508
|
+
for (const header of headers) {
|
|
19509
|
+
if (!header) {
|
|
19510
|
+
continue;
|
|
19511
|
+
}
|
|
19512
|
+
const iterator = header instanceof Headers ? headersEntries7(header) : Object.entries(header);
|
|
19513
|
+
for (const [key, value] of iterator) {
|
|
19514
|
+
if (value === null) {
|
|
19515
|
+
mergedHeaders.delete(key);
|
|
19516
|
+
} else if (Array.isArray(value)) {
|
|
19517
|
+
for (const v2 of value) {
|
|
19518
|
+
mergedHeaders.append(key, v2);
|
|
19519
|
+
}
|
|
19520
|
+
} else if (value !== undefined) {
|
|
19521
|
+
mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
|
|
19522
|
+
}
|
|
19523
|
+
}
|
|
19524
|
+
}
|
|
19525
|
+
return mergedHeaders;
|
|
19526
|
+
}, createInterceptors7 = () => ({
|
|
19527
|
+
error: new Interceptors7,
|
|
19528
|
+
request: new Interceptors7,
|
|
19529
|
+
response: new Interceptors7
|
|
19530
|
+
}), defaultQuerySerializer7, defaultHeaders7, createConfig7 = (override = {}) => ({
|
|
19531
|
+
...jsonBodySerializer7,
|
|
19532
|
+
headers: defaultHeaders7,
|
|
19533
|
+
parseAs: "auto",
|
|
19534
|
+
querySerializer: defaultQuerySerializer7,
|
|
19535
|
+
...override
|
|
19536
|
+
});
|
|
19537
|
+
var init_utils_gen14 = __esm(() => {
|
|
19538
|
+
init_bodySerializer_gen7();
|
|
19539
|
+
init_utils_gen13();
|
|
19540
|
+
defaultQuerySerializer7 = createQuerySerializer7({
|
|
19541
|
+
allowReserved: false,
|
|
19542
|
+
array: {
|
|
19543
|
+
explode: true,
|
|
19544
|
+
style: "form"
|
|
19545
|
+
},
|
|
19546
|
+
object: {
|
|
19547
|
+
explode: true,
|
|
19548
|
+
style: "deepObject"
|
|
19549
|
+
}
|
|
19550
|
+
});
|
|
19551
|
+
defaultHeaders7 = {
|
|
19552
|
+
"Content-Type": "application/json"
|
|
19553
|
+
};
|
|
19554
|
+
});
|
|
19555
|
+
|
|
19556
|
+
// src/generated/qbittorrent/client/client.gen.ts
|
|
19557
|
+
var createClient7 = (config = {}) => {
|
|
19558
|
+
let _config = mergeConfigs7(createConfig7(), config);
|
|
19559
|
+
const getConfig = () => ({ ..._config });
|
|
19560
|
+
const setConfig = (config2) => {
|
|
19561
|
+
_config = mergeConfigs7(_config, config2);
|
|
19562
|
+
return getConfig();
|
|
19563
|
+
};
|
|
19564
|
+
const interceptors = createInterceptors7();
|
|
19565
|
+
const beforeRequest = async (options) => {
|
|
19566
|
+
const opts = {
|
|
19567
|
+
..._config,
|
|
19568
|
+
...options,
|
|
19569
|
+
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
19570
|
+
headers: mergeHeaders7(_config.headers, options.headers),
|
|
19571
|
+
serializedBody: undefined
|
|
19572
|
+
};
|
|
19573
|
+
if (opts.security) {
|
|
19574
|
+
await setAuthParams7({
|
|
19575
|
+
...opts,
|
|
19576
|
+
security: opts.security
|
|
19577
|
+
});
|
|
19578
|
+
}
|
|
19579
|
+
if (opts.requestValidator) {
|
|
19580
|
+
await opts.requestValidator(opts);
|
|
19581
|
+
}
|
|
19582
|
+
if (opts.body !== undefined && opts.bodySerializer) {
|
|
19583
|
+
opts.serializedBody = opts.bodySerializer(opts.body);
|
|
19584
|
+
}
|
|
19585
|
+
if (opts.body === undefined || opts.serializedBody === "") {
|
|
19586
|
+
opts.headers.delete("Content-Type");
|
|
19587
|
+
}
|
|
19588
|
+
const resolvedOpts = opts;
|
|
19589
|
+
const url = buildUrl7(resolvedOpts);
|
|
19590
|
+
return { opts: resolvedOpts, url };
|
|
19591
|
+
};
|
|
19592
|
+
const request = async (options) => {
|
|
19593
|
+
const { opts, url } = await beforeRequest(options);
|
|
19594
|
+
const requestInit = {
|
|
19595
|
+
redirect: "follow",
|
|
19596
|
+
...opts,
|
|
19597
|
+
body: getValidRequestBody7(opts)
|
|
19598
|
+
};
|
|
19599
|
+
let request2 = new Request(url, requestInit);
|
|
19600
|
+
for (const fn of interceptors.request.fns) {
|
|
19601
|
+
if (fn) {
|
|
19602
|
+
request2 = await fn(request2, opts);
|
|
19603
|
+
}
|
|
19604
|
+
}
|
|
19605
|
+
const _fetch = opts.fetch;
|
|
19606
|
+
let response;
|
|
19607
|
+
try {
|
|
19608
|
+
response = await _fetch(request2);
|
|
19609
|
+
} catch (error2) {
|
|
19610
|
+
let finalError2 = error2;
|
|
19611
|
+
for (const fn of interceptors.error.fns) {
|
|
19612
|
+
if (fn) {
|
|
19613
|
+
finalError2 = await fn(error2, undefined, request2, opts);
|
|
19614
|
+
}
|
|
19615
|
+
}
|
|
19616
|
+
finalError2 = finalError2 || {};
|
|
19617
|
+
if (opts.throwOnError) {
|
|
19618
|
+
throw finalError2;
|
|
19619
|
+
}
|
|
19620
|
+
return opts.responseStyle === "data" ? undefined : {
|
|
19621
|
+
error: finalError2,
|
|
19622
|
+
request: request2,
|
|
19623
|
+
response: undefined
|
|
19624
|
+
};
|
|
19625
|
+
}
|
|
19626
|
+
for (const fn of interceptors.response.fns) {
|
|
19627
|
+
if (fn) {
|
|
19628
|
+
response = await fn(response, request2, opts);
|
|
19629
|
+
}
|
|
19630
|
+
}
|
|
19631
|
+
const result = {
|
|
19632
|
+
request: request2,
|
|
19633
|
+
response
|
|
19634
|
+
};
|
|
19635
|
+
if (response.ok) {
|
|
19636
|
+
const parseAs = (opts.parseAs === "auto" ? getParseAs7(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
19637
|
+
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
19638
|
+
let emptyData;
|
|
19639
|
+
switch (parseAs) {
|
|
19640
|
+
case "arrayBuffer":
|
|
19641
|
+
case "blob":
|
|
19642
|
+
case "text":
|
|
19643
|
+
emptyData = await response[parseAs]();
|
|
19644
|
+
break;
|
|
19645
|
+
case "formData":
|
|
19646
|
+
emptyData = new FormData;
|
|
19647
|
+
break;
|
|
19648
|
+
case "stream":
|
|
19649
|
+
emptyData = response.body;
|
|
19650
|
+
break;
|
|
19651
|
+
case "json":
|
|
19652
|
+
default:
|
|
19653
|
+
emptyData = {};
|
|
19654
|
+
break;
|
|
19655
|
+
}
|
|
19656
|
+
return opts.responseStyle === "data" ? emptyData : {
|
|
19657
|
+
data: emptyData,
|
|
19658
|
+
...result
|
|
19659
|
+
};
|
|
19660
|
+
}
|
|
19661
|
+
let data;
|
|
19662
|
+
switch (parseAs) {
|
|
19663
|
+
case "arrayBuffer":
|
|
19664
|
+
case "blob":
|
|
19665
|
+
case "formData":
|
|
19666
|
+
case "text":
|
|
19667
|
+
data = await response[parseAs]();
|
|
19668
|
+
break;
|
|
19669
|
+
case "json": {
|
|
19670
|
+
const text = await response.text();
|
|
19671
|
+
data = text ? JSON.parse(text) : {};
|
|
19672
|
+
break;
|
|
19673
|
+
}
|
|
19674
|
+
case "stream":
|
|
19675
|
+
return opts.responseStyle === "data" ? response.body : {
|
|
19676
|
+
data: response.body,
|
|
19677
|
+
...result
|
|
19678
|
+
};
|
|
19679
|
+
}
|
|
19680
|
+
if (parseAs === "json") {
|
|
19681
|
+
if (opts.responseValidator) {
|
|
19682
|
+
await opts.responseValidator(data);
|
|
19683
|
+
}
|
|
19684
|
+
if (opts.responseTransformer) {
|
|
19685
|
+
data = await opts.responseTransformer(data);
|
|
19686
|
+
}
|
|
19687
|
+
}
|
|
19688
|
+
return opts.responseStyle === "data" ? data : {
|
|
19689
|
+
data,
|
|
19690
|
+
...result
|
|
19691
|
+
};
|
|
19692
|
+
}
|
|
19693
|
+
const textError = await response.text();
|
|
19694
|
+
let jsonError;
|
|
19695
|
+
try {
|
|
19696
|
+
jsonError = JSON.parse(textError);
|
|
19697
|
+
} catch {}
|
|
19698
|
+
const error = jsonError ?? textError;
|
|
19699
|
+
let finalError = error;
|
|
19700
|
+
for (const fn of interceptors.error.fns) {
|
|
19701
|
+
if (fn) {
|
|
19702
|
+
finalError = await fn(error, response, request2, opts);
|
|
19703
|
+
}
|
|
19704
|
+
}
|
|
19705
|
+
finalError = finalError || {};
|
|
19706
|
+
if (opts.throwOnError) {
|
|
19707
|
+
throw finalError;
|
|
19708
|
+
}
|
|
19709
|
+
return opts.responseStyle === "data" ? undefined : {
|
|
19710
|
+
error: finalError,
|
|
19711
|
+
...result
|
|
19712
|
+
};
|
|
19713
|
+
};
|
|
19714
|
+
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
19715
|
+
const makeSseFn = (method) => async (options) => {
|
|
19716
|
+
const { opts, url } = await beforeRequest(options);
|
|
19717
|
+
return createSseClient7({
|
|
19718
|
+
...opts,
|
|
19719
|
+
body: opts.body,
|
|
19720
|
+
headers: opts.headers,
|
|
19721
|
+
method,
|
|
19722
|
+
onRequest: async (url2, init2) => {
|
|
19723
|
+
let request2 = new Request(url2, init2);
|
|
19724
|
+
for (const fn of interceptors.request.fns) {
|
|
19725
|
+
if (fn) {
|
|
19726
|
+
request2 = await fn(request2, opts);
|
|
19727
|
+
}
|
|
19728
|
+
}
|
|
19729
|
+
return request2;
|
|
19730
|
+
},
|
|
19731
|
+
serializedBody: getValidRequestBody7(opts),
|
|
19732
|
+
url
|
|
19733
|
+
});
|
|
19734
|
+
};
|
|
19735
|
+
const _buildUrl = (options) => buildUrl7({ ..._config, ...options });
|
|
19736
|
+
return {
|
|
19737
|
+
buildUrl: _buildUrl,
|
|
19738
|
+
connect: makeMethodFn("CONNECT"),
|
|
19739
|
+
delete: makeMethodFn("DELETE"),
|
|
19740
|
+
get: makeMethodFn("GET"),
|
|
19741
|
+
getConfig,
|
|
19742
|
+
head: makeMethodFn("HEAD"),
|
|
19743
|
+
interceptors,
|
|
19744
|
+
options: makeMethodFn("OPTIONS"),
|
|
19745
|
+
patch: makeMethodFn("PATCH"),
|
|
19746
|
+
post: makeMethodFn("POST"),
|
|
19747
|
+
put: makeMethodFn("PUT"),
|
|
19748
|
+
request,
|
|
19749
|
+
setConfig,
|
|
19750
|
+
sse: {
|
|
19751
|
+
connect: makeSseFn("CONNECT"),
|
|
19752
|
+
delete: makeSseFn("DELETE"),
|
|
19753
|
+
get: makeSseFn("GET"),
|
|
19754
|
+
head: makeSseFn("HEAD"),
|
|
19755
|
+
options: makeSseFn("OPTIONS"),
|
|
19756
|
+
patch: makeSseFn("PATCH"),
|
|
19757
|
+
post: makeSseFn("POST"),
|
|
19758
|
+
put: makeSseFn("PUT"),
|
|
19759
|
+
trace: makeSseFn("TRACE")
|
|
19760
|
+
},
|
|
19761
|
+
trace: makeMethodFn("TRACE")
|
|
19762
|
+
};
|
|
19763
|
+
};
|
|
19764
|
+
var init_client_gen13 = __esm(() => {
|
|
19765
|
+
init_utils_gen13();
|
|
19766
|
+
init_utils_gen14();
|
|
19767
|
+
});
|
|
19768
|
+
|
|
19769
|
+
// src/generated/qbittorrent/client/index.ts
|
|
19770
|
+
var init_client8 = __esm(() => {
|
|
19771
|
+
init_bodySerializer_gen7();
|
|
19772
|
+
init_client_gen13();
|
|
19773
|
+
init_utils_gen14();
|
|
19774
|
+
});
|
|
19775
|
+
|
|
19776
|
+
// src/generated/qbittorrent/client.gen.ts
|
|
19777
|
+
var client7;
|
|
19778
|
+
var init_client_gen14 = __esm(() => {
|
|
19779
|
+
init_client8();
|
|
19780
|
+
client7 = createClient7(createConfig7({ baseUrl: "http://localhost:8080/api/v2" }));
|
|
19781
|
+
});
|
|
19782
|
+
|
|
19783
|
+
// src/generated/qbittorrent/sdk.gen.ts
|
|
19784
|
+
var appVersionGet = (options) => (options?.client ?? client7).get({
|
|
19785
|
+
security: [{
|
|
19786
|
+
in: "cookie",
|
|
19787
|
+
name: "SID",
|
|
19788
|
+
type: "apiKey"
|
|
19789
|
+
}],
|
|
19790
|
+
url: "/app/version",
|
|
19791
|
+
...options
|
|
19792
|
+
}), appWebapiVersionGet = (options) => (options?.client ?? client7).get({
|
|
19793
|
+
security: [{
|
|
19794
|
+
in: "cookie",
|
|
19795
|
+
name: "SID",
|
|
19796
|
+
type: "apiKey"
|
|
19797
|
+
}],
|
|
19798
|
+
url: "/app/webapiVersion",
|
|
19799
|
+
...options
|
|
19800
|
+
}), transferInfoGet = (options) => (options?.client ?? client7).get({
|
|
19801
|
+
security: [{
|
|
19802
|
+
in: "cookie",
|
|
19803
|
+
name: "SID",
|
|
19804
|
+
type: "apiKey"
|
|
19805
|
+
}],
|
|
19806
|
+
url: "/transfer/info",
|
|
19807
|
+
...options
|
|
19808
|
+
}), torrentsInfoPost = (options) => (options.client ?? client7).post({
|
|
19809
|
+
...urlSearchParamsBodySerializer2,
|
|
19810
|
+
security: [{
|
|
19811
|
+
in: "cookie",
|
|
19812
|
+
name: "SID",
|
|
19813
|
+
type: "apiKey"
|
|
19814
|
+
}],
|
|
19815
|
+
url: "/torrents/info",
|
|
19816
|
+
...options,
|
|
19817
|
+
headers: {
|
|
19818
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
19819
|
+
...options.headers
|
|
19820
|
+
}
|
|
19821
|
+
}), torrentsPausePost = (options) => (options.client ?? client7).post({
|
|
19822
|
+
...urlSearchParamsBodySerializer2,
|
|
19823
|
+
security: [{
|
|
19824
|
+
in: "cookie",
|
|
19825
|
+
name: "SID",
|
|
19826
|
+
type: "apiKey"
|
|
19827
|
+
}],
|
|
19828
|
+
url: "/torrents/pause",
|
|
19829
|
+
...options,
|
|
19830
|
+
headers: {
|
|
19831
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
19832
|
+
...options.headers
|
|
19833
|
+
}
|
|
19834
|
+
}), torrentsResumePost = (options) => (options.client ?? client7).post({
|
|
19835
|
+
...urlSearchParamsBodySerializer2,
|
|
19836
|
+
security: [{
|
|
19837
|
+
in: "cookie",
|
|
19838
|
+
name: "SID",
|
|
19839
|
+
type: "apiKey"
|
|
19840
|
+
}],
|
|
19841
|
+
url: "/torrents/resume",
|
|
19842
|
+
...options,
|
|
19843
|
+
headers: {
|
|
19844
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
19845
|
+
...options.headers
|
|
19846
|
+
}
|
|
19847
|
+
}), torrentsDeletePost = (options) => (options.client ?? client7).post({
|
|
19848
|
+
...urlSearchParamsBodySerializer2,
|
|
19849
|
+
security: [{
|
|
19850
|
+
in: "cookie",
|
|
19851
|
+
name: "SID",
|
|
19852
|
+
type: "apiKey"
|
|
19853
|
+
}],
|
|
19854
|
+
url: "/torrents/delete",
|
|
19855
|
+
...options,
|
|
19856
|
+
headers: {
|
|
19857
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
19858
|
+
...options.headers
|
|
19859
|
+
}
|
|
19860
|
+
});
|
|
19861
|
+
var init_sdk_gen7 = __esm(() => {
|
|
19862
|
+
init_client8();
|
|
19863
|
+
init_client_gen14();
|
|
19864
|
+
});
|
|
19865
|
+
|
|
19866
|
+
// src/generated/qbittorrent/index.ts
|
|
19867
|
+
var init_qbittorrent = __esm(() => {
|
|
19868
|
+
init_sdk_gen7();
|
|
19869
|
+
});
|
|
19870
|
+
|
|
19871
|
+
// src/clients/qbittorrent.ts
|
|
19872
|
+
var exports_qbittorrent = {};
|
|
19873
|
+
__export(exports_qbittorrent, {
|
|
19874
|
+
QBittorrentClient: () => QBittorrentClient
|
|
19875
|
+
});
|
|
19876
|
+
|
|
19877
|
+
class QBittorrentClient {
|
|
19878
|
+
baseUrl;
|
|
19879
|
+
username;
|
|
19880
|
+
password;
|
|
19881
|
+
sid = null;
|
|
19882
|
+
constructor(config) {
|
|
19883
|
+
if (!config.baseUrl) {
|
|
19884
|
+
throw new ConnectionError("No base URL provided");
|
|
19885
|
+
}
|
|
19886
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
19887
|
+
this.username = config.username;
|
|
19888
|
+
this.password = config.password;
|
|
19889
|
+
client7.setConfig({
|
|
19890
|
+
baseUrl: `${this.baseUrl}/api/v2`,
|
|
19891
|
+
auth: () => this.ensureAuth()
|
|
19892
|
+
});
|
|
19893
|
+
}
|
|
19894
|
+
async ensureAuth() {
|
|
19895
|
+
if (!this.sid) {
|
|
19896
|
+
await this.login();
|
|
19897
|
+
}
|
|
19898
|
+
return this.sid;
|
|
19899
|
+
}
|
|
19900
|
+
async login() {
|
|
19901
|
+
const response = await fetch(`${this.baseUrl}/api/v2/auth/login`, {
|
|
19902
|
+
method: "POST",
|
|
19903
|
+
headers: {
|
|
19904
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
19905
|
+
Referer: this.baseUrl
|
|
19906
|
+
},
|
|
19907
|
+
body: new URLSearchParams({
|
|
19908
|
+
username: this.username,
|
|
19909
|
+
password: this.password
|
|
19910
|
+
})
|
|
19911
|
+
});
|
|
19912
|
+
if (!response.ok) {
|
|
19913
|
+
throw new ConnectionError(`qBittorrent login failed (${response.status})`);
|
|
19914
|
+
}
|
|
19915
|
+
const text = await response.text();
|
|
19916
|
+
if (text.trim() !== "Ok.") {
|
|
19917
|
+
throw new ConnectionError("qBittorrent authentication failed: invalid username or password");
|
|
19918
|
+
}
|
|
19919
|
+
const setCookie = response.headers.get("set-cookie");
|
|
19920
|
+
const sidMatch = setCookie?.match(/SID=([^;]+)/);
|
|
19921
|
+
if (!sidMatch) {
|
|
19922
|
+
throw new ConnectionError("qBittorrent login succeeded but no SID cookie received");
|
|
19923
|
+
}
|
|
19924
|
+
this.sid = sidMatch[1];
|
|
19925
|
+
}
|
|
19926
|
+
async getAppVersion() {
|
|
19927
|
+
const result = await appVersionGet();
|
|
19928
|
+
return result.data ?? "";
|
|
19929
|
+
}
|
|
19930
|
+
async getApiVersion() {
|
|
19931
|
+
const result = await appWebapiVersionGet();
|
|
19932
|
+
return result.data ?? "";
|
|
19933
|
+
}
|
|
19934
|
+
async getSystemStatus() {
|
|
19935
|
+
const version = await this.getAppVersion();
|
|
19936
|
+
return { version };
|
|
19937
|
+
}
|
|
19938
|
+
async getTransferInfo() {
|
|
19939
|
+
const result = await transferInfoGet();
|
|
19940
|
+
return result.data ?? {};
|
|
19941
|
+
}
|
|
19942
|
+
async getTorrents(filter) {
|
|
19943
|
+
const result = await torrentsInfoPost({
|
|
19944
|
+
body: {
|
|
19945
|
+
...filter ? { filter } : {}
|
|
19946
|
+
}
|
|
19947
|
+
});
|
|
19948
|
+
return result.data ?? [];
|
|
19949
|
+
}
|
|
19950
|
+
async pauseTorrents(hashes) {
|
|
19951
|
+
await torrentsPausePost({
|
|
19952
|
+
body: { hashes: hashes.split("|") }
|
|
19953
|
+
});
|
|
19954
|
+
}
|
|
19955
|
+
async resumeTorrents(hashes) {
|
|
19956
|
+
await torrentsResumePost({
|
|
19957
|
+
body: { hashes: hashes.split("|") }
|
|
19958
|
+
});
|
|
19959
|
+
}
|
|
19960
|
+
async deleteTorrents(hashes, deleteFiles = false) {
|
|
19961
|
+
await torrentsDeletePost({
|
|
19962
|
+
body: { hashes: hashes.split("|"), deleteFiles }
|
|
19963
|
+
});
|
|
19964
|
+
}
|
|
19965
|
+
}
|
|
19966
|
+
var init_qbittorrent2 = __esm(() => {
|
|
19967
|
+
init_errors();
|
|
19968
|
+
init_client_gen14();
|
|
19969
|
+
init_qbittorrent();
|
|
19970
|
+
});
|
|
19971
|
+
|
|
19972
|
+
// src/cli/commands/qbit.ts
|
|
19973
|
+
var exports_qbit = {};
|
|
19974
|
+
__export(exports_qbit, {
|
|
19975
|
+
resources: () => resources7,
|
|
19976
|
+
qbit: () => qbit
|
|
19977
|
+
});
|
|
19978
|
+
var resources7, qbit;
|
|
19979
|
+
var init_qbit = __esm(() => {
|
|
19980
|
+
init_qbittorrent2();
|
|
19981
|
+
init_service();
|
|
19982
|
+
resources7 = [
|
|
19983
|
+
{
|
|
19984
|
+
name: "torrents",
|
|
19985
|
+
description: "Manage torrents",
|
|
19986
|
+
actions: [
|
|
19987
|
+
{
|
|
19988
|
+
name: "list",
|
|
19989
|
+
description: "List torrents",
|
|
19990
|
+
args: [
|
|
19991
|
+
{
|
|
19992
|
+
name: "filter",
|
|
19993
|
+
description: "Filter (all|downloading|seeding|completed|paused|active|inactive|stalled|errored)"
|
|
19994
|
+
}
|
|
19995
|
+
],
|
|
19996
|
+
columns: ["hash", "name", "state", "progress", "size", "dlspeed", "upspeed"],
|
|
19997
|
+
idField: "hash",
|
|
19998
|
+
run: (c3, a2) => c3.getTorrents(a2.filter)
|
|
19999
|
+
},
|
|
20000
|
+
{
|
|
20001
|
+
name: "pause",
|
|
20002
|
+
description: "Pause torrents",
|
|
20003
|
+
args: [
|
|
20004
|
+
{
|
|
20005
|
+
name: "hashes",
|
|
20006
|
+
description: 'Torrent hashes (comma-separated, or "all")',
|
|
20007
|
+
required: true
|
|
20008
|
+
}
|
|
20009
|
+
],
|
|
20010
|
+
run: (c3, a2) => c3.pauseTorrents(a2.hashes)
|
|
20011
|
+
},
|
|
20012
|
+
{
|
|
20013
|
+
name: "resume",
|
|
20014
|
+
description: "Resume torrents",
|
|
20015
|
+
args: [
|
|
20016
|
+
{
|
|
20017
|
+
name: "hashes",
|
|
20018
|
+
description: 'Torrent hashes (comma-separated, or "all")',
|
|
20019
|
+
required: true
|
|
20020
|
+
}
|
|
20021
|
+
],
|
|
20022
|
+
run: (c3, a2) => c3.resumeTorrents(a2.hashes)
|
|
20023
|
+
},
|
|
20024
|
+
{
|
|
20025
|
+
name: "delete",
|
|
20026
|
+
description: "Delete torrents",
|
|
20027
|
+
args: [
|
|
20028
|
+
{
|
|
20029
|
+
name: "hashes",
|
|
20030
|
+
description: 'Torrent hashes (comma-separated, or "all")',
|
|
20031
|
+
required: true
|
|
20032
|
+
},
|
|
20033
|
+
{
|
|
20034
|
+
name: "delete-files",
|
|
20035
|
+
description: "Also delete downloaded files",
|
|
20036
|
+
type: "boolean"
|
|
20037
|
+
}
|
|
20038
|
+
],
|
|
20039
|
+
confirmMessage: "Are you sure you want to delete these torrents?",
|
|
20040
|
+
run: (c3, a2) => c3.deleteTorrents(a2.hashes, a2["delete-files"])
|
|
20041
|
+
}
|
|
20042
|
+
]
|
|
20043
|
+
},
|
|
20044
|
+
{
|
|
20045
|
+
name: "status",
|
|
20046
|
+
description: "Transfer status",
|
|
20047
|
+
actions: [
|
|
20048
|
+
{
|
|
20049
|
+
name: "show",
|
|
20050
|
+
description: "Show transfer info (speed, connections)",
|
|
20051
|
+
columns: [
|
|
20052
|
+
"connection_status",
|
|
20053
|
+
"dl_info_speed",
|
|
20054
|
+
"dl_info_data",
|
|
20055
|
+
"up_info_speed",
|
|
20056
|
+
"up_info_data",
|
|
20057
|
+
"dht_nodes"
|
|
20058
|
+
],
|
|
20059
|
+
run: (c3) => c3.getTransferInfo()
|
|
20060
|
+
}
|
|
20061
|
+
]
|
|
20062
|
+
}
|
|
20063
|
+
];
|
|
20064
|
+
qbit = buildServiceCommand("qbittorrent", "Manage qBittorrent", (config) => new QBittorrentClient(config), resources7);
|
|
20065
|
+
});
|
|
20066
|
+
|
|
20067
|
+
// src/cli/commands/doctor.ts
|
|
20068
|
+
var exports_doctor = {};
|
|
20069
|
+
__export(exports_doctor, {
|
|
20070
|
+
doctor: () => doctor
|
|
20071
|
+
});
|
|
20072
|
+
function classifyError(error) {
|
|
20073
|
+
if (!(error instanceof Error))
|
|
20074
|
+
return "Unknown error";
|
|
20075
|
+
const msg = error.message;
|
|
20076
|
+
const cause = error.cause;
|
|
20077
|
+
if (cause?.code === "ECONNREFUSED" || msg.includes("ECONNREFUSED")) {
|
|
20078
|
+
return "Connection refused - is the service running?";
|
|
20079
|
+
}
|
|
20080
|
+
if (cause?.code === "ENOTFOUND" || msg.includes("ENOTFOUND")) {
|
|
20081
|
+
return "Host not found - check the URL";
|
|
20082
|
+
}
|
|
20083
|
+
if (cause?.code === "ECONNRESET" || msg.includes("ECONNRESET")) {
|
|
20084
|
+
return "Connection reset - service may have crashed";
|
|
20085
|
+
}
|
|
20086
|
+
if (cause?.code === "ETIMEDOUT" || msg.includes("ETIMEDOUT") || msg.includes("timed out")) {
|
|
20087
|
+
return "Connection timed out - service may be unreachable";
|
|
20088
|
+
}
|
|
20089
|
+
if (msg.includes("fetch failed") || msg.includes("Failed to fetch")) {
|
|
20090
|
+
return `Service unreachable - ${cause?.message ?? "check URL and network"}`;
|
|
20091
|
+
}
|
|
20092
|
+
if (msg.includes("401") || msg.includes("Unauthorized")) {
|
|
20093
|
+
return "Authentication failed (401) - check your API key";
|
|
20094
|
+
}
|
|
20095
|
+
if (msg.includes("403") || msg.includes("Forbidden")) {
|
|
20096
|
+
return "Access denied (403) - check your API key permissions";
|
|
20097
|
+
}
|
|
20098
|
+
if (msg.includes("502") || msg.includes("Bad Gateway")) {
|
|
20099
|
+
return "Bad gateway (502) - reverse proxy or service issue";
|
|
20100
|
+
}
|
|
20101
|
+
if (msg.includes("503") || msg.includes("Service Unavailable")) {
|
|
20102
|
+
return "Service unavailable (503) - service may be starting up";
|
|
20103
|
+
}
|
|
20104
|
+
if (msg.includes("CERT") || msg.includes("certificate") || msg.includes("SSL")) {
|
|
20105
|
+
return "SSL/TLS certificate error - check HTTPS configuration";
|
|
20106
|
+
}
|
|
20107
|
+
return msg;
|
|
20108
|
+
}
|
|
20109
|
+
function extractVersion(service, status) {
|
|
20110
|
+
const data = status?.data ?? status;
|
|
20111
|
+
if (typeof data === "string") {
|
|
20112
|
+
return null;
|
|
20113
|
+
}
|
|
20114
|
+
if (service === "bazarr") {
|
|
20115
|
+
return data?.data?.bazarr_version ?? data?.bazarr_version ?? null;
|
|
20116
|
+
}
|
|
20117
|
+
if (service === "qbittorrent") {
|
|
20118
|
+
return data?.version ?? null;
|
|
20119
|
+
}
|
|
20120
|
+
return data?.version ?? status?.version ?? null;
|
|
20121
|
+
}
|
|
20122
|
+
var clientFactories, doctor;
|
|
20123
|
+
var init_doctor = __esm(() => {
|
|
20124
|
+
init_dist();
|
|
20125
|
+
init_dist2();
|
|
20126
|
+
init_bazarr2();
|
|
20127
|
+
init_lidarr2();
|
|
20128
|
+
init_prowlarr2();
|
|
20129
|
+
init_qbittorrent2();
|
|
20130
|
+
init_radarr2();
|
|
20131
|
+
init_readarr2();
|
|
20132
|
+
init_sonarr2();
|
|
20133
|
+
init_config();
|
|
20134
|
+
init_output();
|
|
20135
|
+
clientFactories = {
|
|
20136
|
+
radarr: (c3) => new RadarrClient(c3),
|
|
20137
|
+
sonarr: (c3) => new SonarrClient(c3),
|
|
20138
|
+
lidarr: (c3) => new LidarrClient(c3),
|
|
20139
|
+
readarr: (c3) => new ReadarrClient(c3),
|
|
20140
|
+
prowlarr: (c3) => new ProwlarrClient(c3),
|
|
20141
|
+
bazarr: (c3) => new BazarrClient(c3),
|
|
20142
|
+
qbittorrent: (c3) => new QBittorrentClient(c3)
|
|
20143
|
+
};
|
|
20144
|
+
doctor = defineCommand({
|
|
20145
|
+
meta: {
|
|
20146
|
+
name: "doctor",
|
|
20147
|
+
description: "Test all configured service connections"
|
|
20148
|
+
},
|
|
20149
|
+
args: {
|
|
20150
|
+
json: { type: "boolean", description: "Output as JSON" },
|
|
20151
|
+
table: { type: "boolean", description: "Output as table" },
|
|
20152
|
+
plain: { type: "boolean", description: "Output as TSV (no colors, for piping)" },
|
|
20153
|
+
quiet: { type: "boolean", alias: "q", description: "Output service names only" },
|
|
20154
|
+
select: { type: "string", description: "Cherry-pick fields (comma-separated, JSON mode)" }
|
|
20155
|
+
},
|
|
20156
|
+
async run({ args }) {
|
|
20157
|
+
const format = detectFormat(args);
|
|
20158
|
+
let hasAny = false;
|
|
20159
|
+
const results = [];
|
|
20160
|
+
if (format === "table") {
|
|
20161
|
+
consola.info(`Checking connections...
|
|
20162
|
+
`);
|
|
20163
|
+
}
|
|
20164
|
+
for (const service of SERVICES) {
|
|
20165
|
+
const svcConfig = getServiceConfig(service);
|
|
20166
|
+
if (!svcConfig) {
|
|
20167
|
+
results.push({
|
|
20168
|
+
service,
|
|
20169
|
+
configured: false,
|
|
20170
|
+
status: "not configured"
|
|
20171
|
+
});
|
|
20172
|
+
continue;
|
|
20173
|
+
}
|
|
20174
|
+
hasAny = true;
|
|
20175
|
+
try {
|
|
20176
|
+
const factory = clientFactories[service];
|
|
20177
|
+
if (!factory) {
|
|
20178
|
+
results.push({
|
|
20179
|
+
service,
|
|
20180
|
+
configured: true,
|
|
20181
|
+
status: "fail",
|
|
20182
|
+
baseUrl: svcConfig.baseUrl,
|
|
20183
|
+
error: "No client factory available"
|
|
20184
|
+
});
|
|
20185
|
+
continue;
|
|
20186
|
+
}
|
|
20187
|
+
const client8 = factory(svcConfig);
|
|
20188
|
+
const status = await client8.getSystemStatus();
|
|
20189
|
+
const version = extractVersion(service, status) ?? "?";
|
|
20190
|
+
if (version === "?") {
|
|
20191
|
+
throw new Error("Unexpected response payload");
|
|
20192
|
+
}
|
|
20193
|
+
results.push({
|
|
20194
|
+
service,
|
|
20195
|
+
configured: true,
|
|
20196
|
+
status: "ok",
|
|
20197
|
+
version: String(version),
|
|
20198
|
+
baseUrl: svcConfig.baseUrl
|
|
20199
|
+
});
|
|
20200
|
+
} catch (error) {
|
|
20201
|
+
results.push({
|
|
20202
|
+
service,
|
|
20203
|
+
configured: true,
|
|
20204
|
+
status: "fail",
|
|
20205
|
+
baseUrl: svcConfig.baseUrl,
|
|
20206
|
+
error: classifyError(error)
|
|
20207
|
+
});
|
|
20208
|
+
}
|
|
20209
|
+
}
|
|
20210
|
+
const hadFailure = !hasAny || results.some((r3) => r3.status === "fail");
|
|
20211
|
+
if (!hasAny && format === "table") {
|
|
20212
|
+
consola.warn("\nNo services configured. Run `tsarr config init` to set up.");
|
|
20213
|
+
}
|
|
20214
|
+
formatOutput(results, {
|
|
20215
|
+
format,
|
|
20216
|
+
columns: ["service", "status", "version", "baseUrl", "error"],
|
|
20217
|
+
idField: "service",
|
|
20218
|
+
select: args.select
|
|
20219
|
+
});
|
|
20220
|
+
if (hadFailure) {
|
|
20221
|
+
process.exitCode = 1;
|
|
20222
|
+
}
|
|
20223
|
+
}
|
|
20224
|
+
});
|
|
20225
|
+
});
|
|
20226
|
+
|
|
20227
|
+
// src/cli/commands/config.ts
|
|
20228
|
+
var exports_config = {};
|
|
20229
|
+
__export(exports_config, {
|
|
20230
|
+
config: () => config
|
|
20231
|
+
});
|
|
20232
|
+
var DEFAULT_PORTS, configInit, configSet, configGet, configShow, config;
|
|
20233
|
+
var init_config2 = __esm(() => {
|
|
20234
|
+
init_dist();
|
|
20235
|
+
init_dist2();
|
|
20236
|
+
init_config();
|
|
20237
|
+
init_prompt2();
|
|
20238
|
+
DEFAULT_PORTS = {
|
|
20239
|
+
radarr: 7878,
|
|
20240
|
+
sonarr: 8989,
|
|
20241
|
+
lidarr: 8686,
|
|
20242
|
+
readarr: 8787,
|
|
20243
|
+
prowlarr: 9696,
|
|
20244
|
+
bazarr: 6767,
|
|
20245
|
+
qbittorrent: 8080
|
|
20246
|
+
};
|
|
20247
|
+
configInit = defineCommand({
|
|
20248
|
+
meta: {
|
|
20249
|
+
name: "init",
|
|
20250
|
+
description: "Interactive setup wizard"
|
|
20251
|
+
},
|
|
20252
|
+
async run() {
|
|
20253
|
+
if (!process.stdin.isTTY) {
|
|
20254
|
+
consola.error("Config init requires an interactive terminal.\nUse `tsarr config set` or environment variables for non-interactive setup.");
|
|
20255
|
+
process.exit(1);
|
|
20256
|
+
}
|
|
20257
|
+
consola.info(`Welcome to TsArr CLI setup!
|
|
18982
20258
|
`);
|
|
18983
20259
|
const selected = await promptMultiSelect("Which services do you want to configure?", SERVICES.map((s2) => ({
|
|
18984
20260
|
label: `${s2} (default port: ${DEFAULT_PORTS[s2]})`,
|
|
@@ -18992,32 +20268,45 @@ var init_config2 = __esm(() => {
|
|
|
18992
20268
|
for (const service of selected) {
|
|
18993
20269
|
console.log();
|
|
18994
20270
|
const baseUrl = await promptIfMissing(undefined, `${service} base URL (e.g. http://localhost:${DEFAULT_PORTS[service]})`);
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
|
|
19011
|
-
|
|
19012
|
-
|
|
19013
|
-
|
|
19014
|
-
|
|
19015
|
-
const
|
|
19016
|
-
const
|
|
19017
|
-
|
|
20271
|
+
if (service === "qbittorrent") {
|
|
20272
|
+
const username = await promptIfMissing(undefined, `${service} username`);
|
|
20273
|
+
const password = await promptIfMissing(undefined, `${service} password`);
|
|
20274
|
+
config.services[service] = { baseUrl, username, password };
|
|
20275
|
+
try {
|
|
20276
|
+
const { QBittorrentClient: QBittorrentClient2 } = await Promise.resolve().then(() => (init_qbittorrent2(), exports_qbittorrent));
|
|
20277
|
+
const client8 = new QBittorrentClient2({ baseUrl, username, password });
|
|
20278
|
+
const status = await client8.getSystemStatus();
|
|
20279
|
+
consola.success(`Connected to ${service} v${status.version}`);
|
|
20280
|
+
} catch {
|
|
20281
|
+
consola.warn(`Could not connect to ${service} — config saved anyway.`);
|
|
20282
|
+
}
|
|
20283
|
+
} else {
|
|
20284
|
+
const apiKey = await promptIfMissing(undefined, `${service} API key`);
|
|
20285
|
+
config.services[service] = { baseUrl, apiKey };
|
|
20286
|
+
try {
|
|
20287
|
+
const { RadarrClient: RadarrClient2 } = await Promise.resolve().then(() => (init_radarr2(), exports_radarr));
|
|
20288
|
+
const { SonarrClient: SonarrClient2 } = await Promise.resolve().then(() => (init_sonarr2(), exports_sonarr));
|
|
20289
|
+
const { LidarrClient: LidarrClient2 } = await Promise.resolve().then(() => (init_lidarr2(), exports_lidarr));
|
|
20290
|
+
const { ReadarrClient: ReadarrClient2 } = await Promise.resolve().then(() => (init_readarr2(), exports_readarr));
|
|
20291
|
+
const { ProwlarrClient: ProwlarrClient2 } = await Promise.resolve().then(() => (init_prowlarr2(), exports_prowlarr));
|
|
20292
|
+
const { BazarrClient: BazarrClient2 } = await Promise.resolve().then(() => (init_bazarr2(), exports_bazarr));
|
|
20293
|
+
const factories = {
|
|
20294
|
+
radarr: (c3) => new RadarrClient2(c3),
|
|
20295
|
+
sonarr: (c3) => new SonarrClient2(c3),
|
|
20296
|
+
lidarr: (c3) => new LidarrClient2(c3),
|
|
20297
|
+
readarr: (c3) => new ReadarrClient2(c3),
|
|
20298
|
+
prowlarr: (c3) => new ProwlarrClient2(c3),
|
|
20299
|
+
bazarr: (c3) => new BazarrClient2(c3)
|
|
20300
|
+
};
|
|
20301
|
+
const client8 = factories[service]?.(config.services[service]);
|
|
20302
|
+
if (client8) {
|
|
20303
|
+
const status = await client8.getSystemStatus();
|
|
20304
|
+
const version = status?.data?.version ?? status?.version ?? "?";
|
|
20305
|
+
consola.success(`Connected to ${service} v${version}`);
|
|
20306
|
+
}
|
|
20307
|
+
} catch {
|
|
20308
|
+
consola.warn(`Could not connect to ${service} — config saved anyway.`);
|
|
19018
20309
|
}
|
|
19019
|
-
} catch {
|
|
19020
|
-
consola.warn(`Could not connect to ${service} — config saved anyway.`);
|
|
19021
20310
|
}
|
|
19022
20311
|
}
|
|
19023
20312
|
const location = await promptSelect("Save config to:", [
|
|
@@ -19084,6 +20373,8 @@ var init_config2 = __esm(() => {
|
|
|
19084
20373
|
for (const svc of Object.values(redacted.services)) {
|
|
19085
20374
|
if (svc?.apiKey)
|
|
19086
20375
|
svc.apiKey = "*****";
|
|
20376
|
+
if (svc?.password)
|
|
20377
|
+
svc.password = "*****";
|
|
19087
20378
|
}
|
|
19088
20379
|
}
|
|
19089
20380
|
console.log(JSON.stringify(redacted, null, 2));
|
|
@@ -19111,11 +20402,11 @@ __export(exports_completions, {
|
|
|
19111
20402
|
function generateBashCompletion() {
|
|
19112
20403
|
const services = Object.keys(SERVICE_COMMANDS).join(" ");
|
|
19113
20404
|
const globals = "doctor config completions";
|
|
19114
|
-
const resourceVars = Object.entries(SERVICE_COMMANDS).map(([svc,
|
|
20405
|
+
const resourceVars = Object.entries(SERVICE_COMMANDS).map(([svc, resources8]) => ` local ${svc}_resources="${Object.keys(resources8).join(" ")}"`).join(`
|
|
19115
20406
|
`);
|
|
19116
20407
|
const resourceCases = Object.keys(SERVICE_COMMANDS).map((svc) => ` ${svc}) COMPREPLY=( $(compgen -W "$${svc}_resources" -- "$cur") ) ;;`).join(`
|
|
19117
20408
|
`);
|
|
19118
|
-
const actionCases = Object.entries(SERVICE_COMMANDS).flatMap(([svc,
|
|
20409
|
+
const actionCases = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources8]) => Object.entries(resources8).map(([res, actions]) => ` ${res}) [[ "\${COMP_WORDS[1]}" == "${svc}" ]] && COMPREPLY=( $(compgen -W "${actions.join(" ")}" -- "$cur") ) ;;`)).join(`
|
|
19119
20410
|
`);
|
|
19120
20411
|
return `#!/bin/bash
|
|
19121
20412
|
_tsarr_completions() {
|
|
@@ -19149,9 +20440,9 @@ complete -F _tsarr_completions tsarr`;
|
|
|
19149
20440
|
}
|
|
19150
20441
|
function generateZshCompletion() {
|
|
19151
20442
|
const services = Object.keys(SERVICE_COMMANDS).join(" ");
|
|
19152
|
-
const resourceAssoc = Object.entries(SERVICE_COMMANDS).map(([svc,
|
|
20443
|
+
const resourceAssoc = Object.entries(SERVICE_COMMANDS).map(([svc, resources8]) => ` ${svc} "${Object.keys(resources8).join(" ")}"`).join(`
|
|
19153
20444
|
`);
|
|
19154
|
-
const actionAssoc = Object.entries(SERVICE_COMMANDS).flatMap(([svc,
|
|
20445
|
+
const actionAssoc = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources8]) => Object.entries(resources8).map(([res, actions]) => ` ${svc}:${res} "${actions.join(" ")}"`)).join(`
|
|
19155
20446
|
`);
|
|
19156
20447
|
return `#compdef tsarr
|
|
19157
20448
|
|
|
@@ -19208,12 +20499,12 @@ _tsarr "$@"`;
|
|
|
19208
20499
|
function generateFishCompletion() {
|
|
19209
20500
|
const services = Object.keys(SERVICE_COMMANDS).join(" ");
|
|
19210
20501
|
const globals = "doctor config completions";
|
|
19211
|
-
const resourceCompletions = Object.entries(SERVICE_COMMANDS).map(([svc,
|
|
19212
|
-
const res = Object.keys(
|
|
20502
|
+
const resourceCompletions = Object.entries(SERVICE_COMMANDS).map(([svc, resources8]) => {
|
|
20503
|
+
const res = Object.keys(resources8).join(" ");
|
|
19213
20504
|
return `complete -c tsarr -n "__fish_seen_subcommand_from ${svc}; and not __fish_seen_subcommand_from ${res}" -a "${res}"`;
|
|
19214
20505
|
}).join(`
|
|
19215
20506
|
`);
|
|
19216
|
-
const actionCompletions = Object.entries(SERVICE_COMMANDS).flatMap(([svc,
|
|
20507
|
+
const actionCompletions = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources8]) => Object.entries(resources8).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
20508
|
`);
|
|
19218
20509
|
return `# Fish completions for tsarr
|
|
19219
20510
|
set -l services ${services}
|
|
@@ -19328,7 +20619,7 @@ init_dist();
|
|
|
19328
20619
|
// package.json
|
|
19329
20620
|
var package_default = {
|
|
19330
20621
|
name: "tsarr",
|
|
19331
|
-
version: "2.
|
|
20622
|
+
version: "2.6.0",
|
|
19332
20623
|
author: "Robbe Verhelst",
|
|
19333
20624
|
repository: {
|
|
19334
20625
|
type: "git",
|
|
@@ -19340,16 +20631,16 @@ var package_default = {
|
|
|
19340
20631
|
main: "dist/index.js",
|
|
19341
20632
|
module: "dist/index.js",
|
|
19342
20633
|
devDependencies: {
|
|
19343
|
-
"@biomejs/biome": "2.4.
|
|
19344
|
-
"@hey-api/openapi-ts": "^0.
|
|
20634
|
+
"@biomejs/biome": "2.4.11",
|
|
20635
|
+
"@hey-api/openapi-ts": "^0.96.0",
|
|
19345
20636
|
"@semantic-release/changelog": "^6.0.3",
|
|
19346
20637
|
"@semantic-release/git": "^10.0.1",
|
|
19347
20638
|
"@semantic-release/github": "^12.0.6",
|
|
19348
20639
|
"@semantic-release/npm": "^13.1.5",
|
|
19349
|
-
"@types/bun": "^1.3.
|
|
20640
|
+
"@types/bun": "^1.3.12",
|
|
19350
20641
|
"semantic-release": "^25.0.3",
|
|
19351
|
-
typedoc: "^0.28.
|
|
19352
|
-
typescript: "^
|
|
20642
|
+
typedoc: "^0.28.19",
|
|
20643
|
+
typescript: "^6.0.2"
|
|
19353
20644
|
},
|
|
19354
20645
|
exports: {
|
|
19355
20646
|
".": {
|
|
@@ -19380,6 +20671,10 @@ var package_default = {
|
|
|
19380
20671
|
import: "./dist/clients/bazarr.js",
|
|
19381
20672
|
types: "./dist/clients/bazarr.d.ts"
|
|
19382
20673
|
},
|
|
20674
|
+
"./qbittorrent": {
|
|
20675
|
+
import: "./dist/clients/qbittorrent.js",
|
|
20676
|
+
types: "./dist/clients/qbittorrent.d.ts"
|
|
20677
|
+
},
|
|
19383
20678
|
"./radarr/types": {
|
|
19384
20679
|
types: "./dist/clients/radarr-types.d.ts"
|
|
19385
20680
|
},
|
|
@@ -19397,6 +20692,9 @@ var package_default = {
|
|
|
19397
20692
|
},
|
|
19398
20693
|
"./bazarr/types": {
|
|
19399
20694
|
types: "./dist/clients/bazarr-types.d.ts"
|
|
20695
|
+
},
|
|
20696
|
+
"./qbittorrent/types": {
|
|
20697
|
+
types: "./dist/clients/qbittorrent-types.d.ts"
|
|
19400
20698
|
}
|
|
19401
20699
|
},
|
|
19402
20700
|
description: "Type-safe TypeScript SDK for Servarr APIs (Radarr, Sonarr, etc.)",
|
|
@@ -19415,6 +20713,7 @@ var package_default = {
|
|
|
19415
20713
|
"readarr",
|
|
19416
20714
|
"prowlarr",
|
|
19417
20715
|
"bazarr",
|
|
20716
|
+
"qbittorrent",
|
|
19418
20717
|
"typescript",
|
|
19419
20718
|
"sdk",
|
|
19420
20719
|
"api",
|
|
@@ -19428,7 +20727,7 @@ var package_default = {
|
|
|
19428
20727
|
},
|
|
19429
20728
|
scripts: {
|
|
19430
20729
|
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",
|
|
20730
|
+
"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",
|
|
19432
20731
|
"build:cli": "bun build src/cli/index.ts --outdir dist/cli --target node --format esm && chmod +x dist/cli/index.js",
|
|
19433
20732
|
"build:types": "tsc --project tsconfig.build.json",
|
|
19434
20733
|
prepublishOnly: "bun run build",
|
|
@@ -19455,7 +20754,7 @@ var package_default = {
|
|
|
19455
20754
|
type: "module",
|
|
19456
20755
|
types: "dist/index.d.ts",
|
|
19457
20756
|
dependencies: {
|
|
19458
|
-
citty: "^0.2.
|
|
20757
|
+
citty: "^0.2.2",
|
|
19459
20758
|
consola: "^3.4.2"
|
|
19460
20759
|
}
|
|
19461
20760
|
};
|
|
@@ -19466,7 +20765,7 @@ var main = defineCommand({
|
|
|
19466
20765
|
meta: {
|
|
19467
20766
|
name: "tsarr",
|
|
19468
20767
|
version,
|
|
19469
|
-
description: "Type-safe CLI for Servarr APIs (Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr)"
|
|
20768
|
+
description: "Type-safe CLI for Servarr APIs (Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr, qBittorrent)"
|
|
19470
20769
|
},
|
|
19471
20770
|
subCommands: {
|
|
19472
20771
|
radarr: () => Promise.resolve().then(() => (init_radarr3(), exports_radarr3)).then((m2) => m2.radarr),
|
|
@@ -19475,6 +20774,7 @@ var main = defineCommand({
|
|
|
19475
20774
|
readarr: () => Promise.resolve().then(() => (init_readarr3(), exports_readarr3)).then((m2) => m2.readarr),
|
|
19476
20775
|
prowlarr: () => Promise.resolve().then(() => (init_prowlarr3(), exports_prowlarr3)).then((m2) => m2.prowlarr),
|
|
19477
20776
|
bazarr: () => Promise.resolve().then(() => (init_bazarr3(), exports_bazarr3)).then((m2) => m2.bazarr),
|
|
20777
|
+
qbit: () => Promise.resolve().then(() => (init_qbit(), exports_qbit)).then((m2) => m2.qbit),
|
|
19478
20778
|
doctor: () => Promise.resolve().then(() => (init_doctor(), exports_doctor)).then((m2) => m2.doctor),
|
|
19479
20779
|
config: () => Promise.resolve().then(() => (init_config2(), exports_config)).then((m2) => m2.config),
|
|
19480
20780
|
completions: () => Promise.resolve().then(() => (init_completions(), exports_completions)).then((m2) => m2.completions)
|