tsarr 2.6.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +4 -3
  2. package/dist/cli/commands/config.d.ts.map +1 -1
  3. package/dist/cli/commands/doctor.d.ts.map +1 -1
  4. package/dist/cli/commands/seerr.d.ts +4 -0
  5. package/dist/cli/commands/seerr.d.ts.map +1 -0
  6. package/dist/cli/commands/service.d.ts.map +1 -1
  7. package/dist/cli/completions.d.ts.map +1 -1
  8. package/dist/cli/config.d.ts +1 -1
  9. package/dist/cli/config.d.ts.map +1 -1
  10. package/dist/cli/index.js +1174 -73
  11. package/dist/cli/output.d.ts.map +1 -1
  12. package/dist/clients/seerr-types.d.ts +2 -0
  13. package/dist/clients/seerr-types.d.ts.map +1 -0
  14. package/dist/clients/seerr.d.ts +158 -0
  15. package/dist/clients/seerr.d.ts.map +1 -0
  16. package/dist/clients/seerr.js +1009 -0
  17. package/dist/generated/seerr/client/client.gen.d.ts +3 -0
  18. package/dist/generated/seerr/client/client.gen.d.ts.map +1 -0
  19. package/dist/generated/seerr/client/index.d.ts +9 -0
  20. package/dist/generated/seerr/client/index.d.ts.map +1 -0
  21. package/dist/generated/seerr/client/types.gen.d.ts +118 -0
  22. package/dist/generated/seerr/client/types.gen.d.ts.map +1 -0
  23. package/dist/generated/seerr/client/utils.gen.d.ts +34 -0
  24. package/dist/generated/seerr/client/utils.gen.d.ts.map +1 -0
  25. package/dist/generated/seerr/client.gen.d.ts +13 -0
  26. package/dist/generated/seerr/client.gen.d.ts.map +1 -0
  27. package/dist/generated/seerr/core/auth.gen.d.ts +19 -0
  28. package/dist/generated/seerr/core/auth.gen.d.ts.map +1 -0
  29. package/dist/generated/seerr/core/bodySerializer.gen.d.ts +26 -0
  30. package/dist/generated/seerr/core/bodySerializer.gen.d.ts.map +1 -0
  31. package/dist/generated/seerr/core/params.gen.d.ts +44 -0
  32. package/dist/generated/seerr/core/params.gen.d.ts.map +1 -0
  33. package/dist/generated/seerr/core/pathSerializer.gen.d.ts +34 -0
  34. package/dist/generated/seerr/core/pathSerializer.gen.d.ts.map +1 -0
  35. package/dist/generated/seerr/core/queryKeySerializer.gen.d.ts +19 -0
  36. package/dist/generated/seerr/core/queryKeySerializer.gen.d.ts.map +1 -0
  37. package/dist/generated/seerr/core/serverSentEvents.gen.d.ts +72 -0
  38. package/dist/generated/seerr/core/serverSentEvents.gen.d.ts.map +1 -0
  39. package/dist/generated/seerr/core/types.gen.d.ts +79 -0
  40. package/dist/generated/seerr/core/types.gen.d.ts.map +1 -0
  41. package/dist/generated/seerr/core/utils.gen.d.ts +20 -0
  42. package/dist/generated/seerr/core/utils.gen.d.ts.map +1 -0
  43. package/dist/generated/seerr/index.d.ts +3 -0
  44. package/dist/generated/seerr/index.d.ts.map +1 -0
  45. package/dist/generated/seerr/sdk.gen.d.ts +1309 -0
  46. package/dist/generated/seerr/sdk.gen.d.ts.map +1 -0
  47. package/dist/generated/seerr/types.gen.d.ts +4867 -0
  48. package/dist/generated/seerr/types.gen.d.ts.map +1 -0
  49. package/dist/index.d.ts +2 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +41 -36
  52. package/dist/tsarr-2.7.1.tgz +0 -0
  53. package/package.json +12 -2
  54. package/dist/tsarr-2.6.0.tgz +0 -0
package/dist/cli/index.js CHANGED
@@ -5080,7 +5080,8 @@ var init_config = __esm(() => {
5080
5080
  "readarr",
5081
5081
  "prowlarr",
5082
5082
  "bazarr",
5083
- "qbittorrent"
5083
+ "qbittorrent",
5084
+ "seerr"
5084
5085
  ];
5085
5086
  GLOBAL_CONFIG_DIR = join(homedir(), ".config", "tsarr");
5086
5087
  GLOBAL_CONFIG_PATH = join(GLOBAL_CONFIG_DIR, "config.json");
@@ -5108,7 +5109,12 @@ function formatOutput(data, options) {
5108
5109
  }
5109
5110
  switch (options.format) {
5110
5111
  case "json": {
5111
- const output = options.select ? selectFields(data, options.select) : data;
5112
+ let output = data;
5113
+ if (options.select) {
5114
+ output = selectFields(data, options.select);
5115
+ } else if (options.columns && Array.isArray(data)) {
5116
+ output = selectFields(data, options.columns.join(","));
5117
+ }
5112
5118
  console.log(JSON.stringify(output, null, 2));
5113
5119
  break;
5114
5120
  }
@@ -5382,7 +5388,7 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
5382
5388
  const format = detectFormat(args);
5383
5389
  const noHeader = process.argv.includes("--no-header") || !!args.noHeader;
5384
5390
  const dryRun = !!(args["dry-run"] ?? args.dryRun ?? process.argv.includes("--dry-run"));
5385
- if (dryRun && isWriteAction(action.name)) {
5391
+ if (dryRun) {
5386
5392
  formatOutput(buildDryRunPreview(format, serviceName, resource.name, action.name, resolvedArgs), {
5387
5393
  format,
5388
5394
  noHeader
@@ -5417,6 +5423,8 @@ Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY`;
5417
5423
  }
5418
5424
  if (result?.records !== undefined && Array.isArray(result.records)) {
5419
5425
  result = result.records;
5426
+ } else if (result?.results !== undefined && Array.isArray(result.results)) {
5427
+ result = result.results;
5420
5428
  }
5421
5429
  formatOutput(result, {
5422
5430
  format,
@@ -5431,12 +5439,14 @@ Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY`;
5431
5439
  }
5432
5440
  });
5433
5441
  }
5442
+ const singleAction = resource.actions.length === 1 ? actionCommands[resource.actions[0].name] : undefined;
5434
5443
  subCommands[resource.name] = defineCommand({
5435
5444
  meta: {
5436
5445
  name: resource.name,
5437
5446
  description: resource.description
5438
5447
  },
5439
- subCommands: actionCommands
5448
+ subCommands: actionCommands,
5449
+ ...singleAction ? { run: singleAction.run } : {}
5440
5450
  });
5441
5451
  }
5442
5452
  return defineCommand({
@@ -5459,22 +5469,6 @@ function coerceBooleanArg(value) {
5459
5469
  }
5460
5470
  return Boolean(value);
5461
5471
  }
5462
- function isWriteAction(actionName) {
5463
- return [
5464
- "add",
5465
- "create",
5466
- "delete",
5467
- "edit",
5468
- "pause",
5469
- "resume",
5470
- "refresh",
5471
- "manual-search",
5472
- "grab",
5473
- "sync",
5474
- "test",
5475
- "search"
5476
- ].includes(actionName);
5477
- }
5478
5472
  function buildDryRunPreview(format, serviceName, resourceName, actionName, args) {
5479
5473
  const filteredArgs = Object.fromEntries(Object.entries(args).filter(([key, value]) => value !== undefined && key !== "_" && key !== "json" && key !== "table" && key !== "plain" && key !== "quiet" && key !== "select" && key !== "no-header" && key !== "noHeader" && key !== "dry-run" && key !== "dryRun"));
5480
5474
  if (format === "json") {
@@ -20064,45 +20058,1130 @@ var init_qbit = __esm(() => {
20064
20058
  qbit = buildServiceCommand("qbittorrent", "Manage qBittorrent", (config) => new QBittorrentClient(config), resources7);
20065
20059
  });
20066
20060
 
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";
20061
+ // src/generated/seerr/core/serverSentEvents.gen.ts
20062
+ function createSseClient8({
20063
+ onRequest,
20064
+ onSseError,
20065
+ onSseEvent,
20066
+ responseTransformer,
20067
+ responseValidator,
20068
+ sseDefaultRetryDelay,
20069
+ sseMaxRetryAttempts,
20070
+ sseMaxRetryDelay,
20071
+ sseSleepFn,
20072
+ url,
20073
+ ...options
20074
+ }) {
20075
+ let lastEventId;
20076
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
20077
+ const createStream = async function* () {
20078
+ let retryDelay = sseDefaultRetryDelay ?? 3000;
20079
+ let attempt = 0;
20080
+ const signal = options.signal ?? new AbortController().signal;
20081
+ while (true) {
20082
+ if (signal.aborted)
20083
+ break;
20084
+ attempt++;
20085
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
20086
+ if (lastEventId !== undefined) {
20087
+ headers.set("Last-Event-ID", lastEventId);
20088
+ }
20089
+ try {
20090
+ const requestInit = {
20091
+ redirect: "follow",
20092
+ ...options,
20093
+ body: options.serializedBody,
20094
+ headers,
20095
+ signal
20096
+ };
20097
+ let request = new Request(url, requestInit);
20098
+ if (onRequest) {
20099
+ request = await onRequest(url, requestInit);
20100
+ }
20101
+ const _fetch = options.fetch ?? globalThis.fetch;
20102
+ const response = await _fetch(request);
20103
+ if (!response.ok)
20104
+ throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
20105
+ if (!response.body)
20106
+ throw new Error("No body in SSE response");
20107
+ const reader = response.body.pipeThrough(new TextDecoderStream).getReader();
20108
+ let buffer = "";
20109
+ const abortHandler = () => {
20110
+ try {
20111
+ reader.cancel();
20112
+ } catch {}
20113
+ };
20114
+ signal.addEventListener("abort", abortHandler);
20115
+ try {
20116
+ while (true) {
20117
+ const { done, value } = await reader.read();
20118
+ if (done)
20119
+ break;
20120
+ buffer += value;
20121
+ buffer = buffer.replace(/\r\n?/g, `
20122
+ `);
20123
+ const chunks = buffer.split(`
20124
+
20125
+ `);
20126
+ buffer = chunks.pop() ?? "";
20127
+ for (const chunk of chunks) {
20128
+ const lines = chunk.split(`
20129
+ `);
20130
+ const dataLines = [];
20131
+ let eventName;
20132
+ for (const line of lines) {
20133
+ if (line.startsWith("data:")) {
20134
+ dataLines.push(line.replace(/^data:\s*/, ""));
20135
+ } else if (line.startsWith("event:")) {
20136
+ eventName = line.replace(/^event:\s*/, "");
20137
+ } else if (line.startsWith("id:")) {
20138
+ lastEventId = line.replace(/^id:\s*/, "");
20139
+ } else if (line.startsWith("retry:")) {
20140
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
20141
+ if (!Number.isNaN(parsed)) {
20142
+ retryDelay = parsed;
20143
+ }
20144
+ }
20145
+ }
20146
+ let data;
20147
+ let parsedJson = false;
20148
+ if (dataLines.length) {
20149
+ const rawData = dataLines.join(`
20150
+ `);
20151
+ try {
20152
+ data = JSON.parse(rawData);
20153
+ parsedJson = true;
20154
+ } catch {
20155
+ data = rawData;
20156
+ }
20157
+ }
20158
+ if (parsedJson) {
20159
+ if (responseValidator) {
20160
+ await responseValidator(data);
20161
+ }
20162
+ if (responseTransformer) {
20163
+ data = await responseTransformer(data);
20164
+ }
20165
+ }
20166
+ onSseEvent?.({
20167
+ data,
20168
+ event: eventName,
20169
+ id: lastEventId,
20170
+ retry: retryDelay
20171
+ });
20172
+ if (dataLines.length) {
20173
+ yield data;
20174
+ }
20175
+ }
20176
+ }
20177
+ } finally {
20178
+ signal.removeEventListener("abort", abortHandler);
20179
+ reader.releaseLock();
20180
+ }
20181
+ break;
20182
+ } catch (error) {
20183
+ onSseError?.(error);
20184
+ if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
20185
+ break;
20186
+ }
20187
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
20188
+ await sleep(backoff);
20189
+ }
20190
+ }
20191
+ };
20192
+ const stream = createStream();
20193
+ return { stream };
20194
+ }
20195
+
20196
+ // src/generated/seerr/core/pathSerializer.gen.ts
20197
+ var separatorArrayExplode8 = (style) => {
20198
+ switch (style) {
20199
+ case "label":
20200
+ return ".";
20201
+ case "matrix":
20202
+ return ";";
20203
+ case "simple":
20204
+ return ",";
20205
+ default:
20206
+ return "&";
20082
20207
  }
20083
- if (cause?.code === "ECONNRESET" || msg.includes("ECONNRESET")) {
20084
- return "Connection reset - service may have crashed";
20208
+ }, separatorArrayNoExplode8 = (style) => {
20209
+ switch (style) {
20210
+ case "form":
20211
+ return ",";
20212
+ case "pipeDelimited":
20213
+ return "|";
20214
+ case "spaceDelimited":
20215
+ return "%20";
20216
+ default:
20217
+ return ",";
20085
20218
  }
20086
- if (cause?.code === "ETIMEDOUT" || msg.includes("ETIMEDOUT") || msg.includes("timed out")) {
20087
- return "Connection timed out - service may be unreachable";
20219
+ }, separatorObjectExplode8 = (style) => {
20220
+ switch (style) {
20221
+ case "label":
20222
+ return ".";
20223
+ case "matrix":
20224
+ return ";";
20225
+ case "simple":
20226
+ return ",";
20227
+ default:
20228
+ return "&";
20088
20229
  }
20089
- if (msg.includes("fetch failed") || msg.includes("Failed to fetch")) {
20090
- return `Service unreachable - ${cause?.message ?? "check URL and network"}`;
20230
+ }, serializeArrayParam8 = ({
20231
+ allowReserved,
20232
+ explode,
20233
+ name,
20234
+ style,
20235
+ value
20236
+ }) => {
20237
+ if (!explode) {
20238
+ const joinedValues2 = (allowReserved ? value : value.map((v2) => encodeURIComponent(v2))).join(separatorArrayNoExplode8(style));
20239
+ switch (style) {
20240
+ case "label":
20241
+ return `.${joinedValues2}`;
20242
+ case "matrix":
20243
+ return `;${name}=${joinedValues2}`;
20244
+ case "simple":
20245
+ return joinedValues2;
20246
+ default:
20247
+ return `${name}=${joinedValues2}`;
20248
+ }
20091
20249
  }
20092
- if (msg.includes("401") || msg.includes("Unauthorized")) {
20093
- return "Authentication failed (401) - check your API key";
20250
+ const separator = separatorArrayExplode8(style);
20251
+ const joinedValues = value.map((v2) => {
20252
+ if (style === "label" || style === "simple") {
20253
+ return allowReserved ? v2 : encodeURIComponent(v2);
20254
+ }
20255
+ return serializePrimitiveParam8({
20256
+ allowReserved,
20257
+ name,
20258
+ value: v2
20259
+ });
20260
+ }).join(separator);
20261
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
20262
+ }, serializePrimitiveParam8 = ({
20263
+ allowReserved,
20264
+ name,
20265
+ value
20266
+ }) => {
20267
+ if (value === undefined || value === null) {
20268
+ return "";
20094
20269
  }
20095
- if (msg.includes("403") || msg.includes("Forbidden")) {
20096
- return "Access denied (403) - check your API key permissions";
20270
+ if (typeof value === "object") {
20271
+ throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
20097
20272
  }
20098
- if (msg.includes("502") || msg.includes("Bad Gateway")) {
20099
- return "Bad gateway (502) - reverse proxy or service issue";
20273
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
20274
+ }, serializeObjectParam8 = ({
20275
+ allowReserved,
20276
+ explode,
20277
+ name,
20278
+ style,
20279
+ value,
20280
+ valueOnly
20281
+ }) => {
20282
+ if (value instanceof Date) {
20283
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
20100
20284
  }
20101
- if (msg.includes("503") || msg.includes("Service Unavailable")) {
20102
- return "Service unavailable (503) - service may be starting up";
20285
+ if (style !== "deepObject" && !explode) {
20286
+ let values = [];
20287
+ Object.entries(value).forEach(([key, v2]) => {
20288
+ values = [...values, key, allowReserved ? v2 : encodeURIComponent(v2)];
20289
+ });
20290
+ const joinedValues2 = values.join(",");
20291
+ switch (style) {
20292
+ case "form":
20293
+ return `${name}=${joinedValues2}`;
20294
+ case "label":
20295
+ return `.${joinedValues2}`;
20296
+ case "matrix":
20297
+ return `;${name}=${joinedValues2}`;
20298
+ default:
20299
+ return joinedValues2;
20300
+ }
20103
20301
  }
20104
- if (msg.includes("CERT") || msg.includes("certificate") || msg.includes("SSL")) {
20105
- return "SSL/TLS certificate error - check HTTPS configuration";
20302
+ const separator = separatorObjectExplode8(style);
20303
+ const joinedValues = Object.entries(value).map(([key, v2]) => serializePrimitiveParam8({
20304
+ allowReserved,
20305
+ name: style === "deepObject" ? `${name}[${key}]` : key,
20306
+ value: v2
20307
+ })).join(separator);
20308
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
20309
+ };
20310
+
20311
+ // src/generated/seerr/core/utils.gen.ts
20312
+ function getValidRequestBody8(options) {
20313
+ const hasBody = options.body !== undefined;
20314
+ const isSerializedBody = hasBody && options.bodySerializer;
20315
+ if (isSerializedBody) {
20316
+ if ("serializedBody" in options) {
20317
+ const hasSerializedBody = options.serializedBody !== undefined && options.serializedBody !== "";
20318
+ return hasSerializedBody ? options.serializedBody : null;
20319
+ }
20320
+ return options.body !== "" ? options.body : null;
20321
+ }
20322
+ if (hasBody) {
20323
+ return options.body;
20324
+ }
20325
+ return;
20326
+ }
20327
+ var PATH_PARAM_RE8, defaultPathSerializer8 = ({ path, url: _url }) => {
20328
+ let url = _url;
20329
+ const matches = _url.match(PATH_PARAM_RE8);
20330
+ if (matches) {
20331
+ for (const match of matches) {
20332
+ let explode = false;
20333
+ let name = match.substring(1, match.length - 1);
20334
+ let style = "simple";
20335
+ if (name.endsWith("*")) {
20336
+ explode = true;
20337
+ name = name.substring(0, name.length - 1);
20338
+ }
20339
+ if (name.startsWith(".")) {
20340
+ name = name.substring(1);
20341
+ style = "label";
20342
+ } else if (name.startsWith(";")) {
20343
+ name = name.substring(1);
20344
+ style = "matrix";
20345
+ }
20346
+ const value = path[name];
20347
+ if (value === undefined || value === null) {
20348
+ continue;
20349
+ }
20350
+ if (Array.isArray(value)) {
20351
+ url = url.replace(match, serializeArrayParam8({ explode, name, style, value }));
20352
+ continue;
20353
+ }
20354
+ if (typeof value === "object") {
20355
+ url = url.replace(match, serializeObjectParam8({
20356
+ explode,
20357
+ name,
20358
+ style,
20359
+ value,
20360
+ valueOnly: true
20361
+ }));
20362
+ continue;
20363
+ }
20364
+ if (style === "matrix") {
20365
+ url = url.replace(match, `;${serializePrimitiveParam8({
20366
+ name,
20367
+ value
20368
+ })}`);
20369
+ continue;
20370
+ }
20371
+ const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
20372
+ url = url.replace(match, replaceValue);
20373
+ }
20374
+ }
20375
+ return url;
20376
+ }, getUrl8 = ({
20377
+ baseUrl,
20378
+ path,
20379
+ query,
20380
+ querySerializer,
20381
+ url: _url
20382
+ }) => {
20383
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
20384
+ let url = (baseUrl ?? "") + pathUrl;
20385
+ if (path) {
20386
+ url = defaultPathSerializer8({ path, url });
20387
+ }
20388
+ let search = query ? querySerializer(query) : "";
20389
+ if (search.startsWith("?")) {
20390
+ search = search.substring(1);
20391
+ }
20392
+ if (search) {
20393
+ url += `?${search}`;
20394
+ }
20395
+ return url;
20396
+ };
20397
+ var init_utils_gen15 = __esm(() => {
20398
+ PATH_PARAM_RE8 = /\{[^{}]+\}/g;
20399
+ });
20400
+
20401
+ // src/generated/seerr/core/auth.gen.ts
20402
+ var getAuthToken8 = async (auth, callback) => {
20403
+ const token = typeof callback === "function" ? await callback(auth) : callback;
20404
+ if (!token) {
20405
+ return;
20406
+ }
20407
+ if (auth.scheme === "bearer") {
20408
+ return `Bearer ${token}`;
20409
+ }
20410
+ if (auth.scheme === "basic") {
20411
+ return `Basic ${btoa(token)}`;
20412
+ }
20413
+ return token;
20414
+ };
20415
+
20416
+ // src/generated/seerr/core/bodySerializer.gen.ts
20417
+ var jsonBodySerializer8;
20418
+ var init_bodySerializer_gen8 = __esm(() => {
20419
+ jsonBodySerializer8 = {
20420
+ bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
20421
+ };
20422
+ });
20423
+
20424
+ // src/generated/seerr/client/utils.gen.ts
20425
+ class Interceptors8 {
20426
+ fns = [];
20427
+ clear() {
20428
+ this.fns = [];
20429
+ }
20430
+ eject(id) {
20431
+ const index = this.getInterceptorIndex(id);
20432
+ if (this.fns[index]) {
20433
+ this.fns[index] = null;
20434
+ }
20435
+ }
20436
+ exists(id) {
20437
+ const index = this.getInterceptorIndex(id);
20438
+ return Boolean(this.fns[index]);
20439
+ }
20440
+ getInterceptorIndex(id) {
20441
+ if (typeof id === "number") {
20442
+ return this.fns[id] ? id : -1;
20443
+ }
20444
+ return this.fns.indexOf(id);
20445
+ }
20446
+ update(id, fn) {
20447
+ const index = this.getInterceptorIndex(id);
20448
+ if (this.fns[index]) {
20449
+ this.fns[index] = fn;
20450
+ return id;
20451
+ }
20452
+ return false;
20453
+ }
20454
+ use(fn) {
20455
+ this.fns.push(fn);
20456
+ return this.fns.length - 1;
20457
+ }
20458
+ }
20459
+ var createQuerySerializer8 = ({
20460
+ parameters = {},
20461
+ ...args
20462
+ } = {}) => {
20463
+ const querySerializer = (queryParams) => {
20464
+ const search = [];
20465
+ if (queryParams && typeof queryParams === "object") {
20466
+ for (const name in queryParams) {
20467
+ const value = queryParams[name];
20468
+ if (value === undefined || value === null) {
20469
+ continue;
20470
+ }
20471
+ const options = parameters[name] || args;
20472
+ if (Array.isArray(value)) {
20473
+ const serializedArray = serializeArrayParam8({
20474
+ allowReserved: options.allowReserved,
20475
+ explode: true,
20476
+ name,
20477
+ style: "form",
20478
+ value,
20479
+ ...options.array
20480
+ });
20481
+ if (serializedArray)
20482
+ search.push(serializedArray);
20483
+ } else if (typeof value === "object") {
20484
+ const serializedObject = serializeObjectParam8({
20485
+ allowReserved: options.allowReserved,
20486
+ explode: true,
20487
+ name,
20488
+ style: "deepObject",
20489
+ value,
20490
+ ...options.object
20491
+ });
20492
+ if (serializedObject)
20493
+ search.push(serializedObject);
20494
+ } else {
20495
+ const serializedPrimitive = serializePrimitiveParam8({
20496
+ allowReserved: options.allowReserved,
20497
+ name,
20498
+ value
20499
+ });
20500
+ if (serializedPrimitive)
20501
+ search.push(serializedPrimitive);
20502
+ }
20503
+ }
20504
+ }
20505
+ return search.join("&");
20506
+ };
20507
+ return querySerializer;
20508
+ }, getParseAs8 = (contentType) => {
20509
+ if (!contentType) {
20510
+ return "stream";
20511
+ }
20512
+ const cleanContent = contentType.split(";")[0]?.trim();
20513
+ if (!cleanContent) {
20514
+ return;
20515
+ }
20516
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
20517
+ return "json";
20518
+ }
20519
+ if (cleanContent === "multipart/form-data") {
20520
+ return "formData";
20521
+ }
20522
+ if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
20523
+ return "blob";
20524
+ }
20525
+ if (cleanContent.startsWith("text/")) {
20526
+ return "text";
20527
+ }
20528
+ return;
20529
+ }, checkForExistence8 = (options, name) => {
20530
+ if (!name) {
20531
+ return false;
20532
+ }
20533
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
20534
+ return true;
20535
+ }
20536
+ return false;
20537
+ }, setAuthParams8 = async ({
20538
+ security,
20539
+ ...options
20540
+ }) => {
20541
+ for (const auth of security) {
20542
+ if (checkForExistence8(options, auth.name)) {
20543
+ continue;
20544
+ }
20545
+ const token = await getAuthToken8(auth, options.auth);
20546
+ if (!token) {
20547
+ continue;
20548
+ }
20549
+ const name = auth.name ?? "Authorization";
20550
+ switch (auth.in) {
20551
+ case "query":
20552
+ if (!options.query) {
20553
+ options.query = {};
20554
+ }
20555
+ options.query[name] = token;
20556
+ break;
20557
+ case "cookie":
20558
+ options.headers.append("Cookie", `${name}=${token}`);
20559
+ break;
20560
+ case "header":
20561
+ default:
20562
+ options.headers.set(name, token);
20563
+ break;
20564
+ }
20565
+ }
20566
+ }, buildUrl8 = (options) => getUrl8({
20567
+ baseUrl: options.baseUrl,
20568
+ path: options.path,
20569
+ query: options.query,
20570
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer8(options.querySerializer),
20571
+ url: options.url
20572
+ }), mergeConfigs8 = (a2, b2) => {
20573
+ const config = { ...a2, ...b2 };
20574
+ if (config.baseUrl?.endsWith("/")) {
20575
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
20576
+ }
20577
+ config.headers = mergeHeaders8(a2.headers, b2.headers);
20578
+ return config;
20579
+ }, headersEntries8 = (headers) => {
20580
+ const entries = [];
20581
+ headers.forEach((value, key) => {
20582
+ entries.push([key, value]);
20583
+ });
20584
+ return entries;
20585
+ }, mergeHeaders8 = (...headers) => {
20586
+ const mergedHeaders = new Headers;
20587
+ for (const header of headers) {
20588
+ if (!header) {
20589
+ continue;
20590
+ }
20591
+ const iterator = header instanceof Headers ? headersEntries8(header) : Object.entries(header);
20592
+ for (const [key, value] of iterator) {
20593
+ if (value === null) {
20594
+ mergedHeaders.delete(key);
20595
+ } else if (Array.isArray(value)) {
20596
+ for (const v2 of value) {
20597
+ mergedHeaders.append(key, v2);
20598
+ }
20599
+ } else if (value !== undefined) {
20600
+ mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
20601
+ }
20602
+ }
20603
+ }
20604
+ return mergedHeaders;
20605
+ }, createInterceptors8 = () => ({
20606
+ error: new Interceptors8,
20607
+ request: new Interceptors8,
20608
+ response: new Interceptors8
20609
+ }), defaultQuerySerializer8, defaultHeaders8, createConfig8 = (override = {}) => ({
20610
+ ...jsonBodySerializer8,
20611
+ headers: defaultHeaders8,
20612
+ parseAs: "auto",
20613
+ querySerializer: defaultQuerySerializer8,
20614
+ ...override
20615
+ });
20616
+ var init_utils_gen16 = __esm(() => {
20617
+ init_bodySerializer_gen8();
20618
+ init_utils_gen15();
20619
+ defaultQuerySerializer8 = createQuerySerializer8({
20620
+ allowReserved: false,
20621
+ array: {
20622
+ explode: true,
20623
+ style: "form"
20624
+ },
20625
+ object: {
20626
+ explode: true,
20627
+ style: "deepObject"
20628
+ }
20629
+ });
20630
+ defaultHeaders8 = {
20631
+ "Content-Type": "application/json"
20632
+ };
20633
+ });
20634
+
20635
+ // src/generated/seerr/client/client.gen.ts
20636
+ var createClient8 = (config = {}) => {
20637
+ let _config = mergeConfigs8(createConfig8(), config);
20638
+ const getConfig = () => ({ ..._config });
20639
+ const setConfig = (config2) => {
20640
+ _config = mergeConfigs8(_config, config2);
20641
+ return getConfig();
20642
+ };
20643
+ const interceptors = createInterceptors8();
20644
+ const beforeRequest = async (options) => {
20645
+ const opts = {
20646
+ ..._config,
20647
+ ...options,
20648
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
20649
+ headers: mergeHeaders8(_config.headers, options.headers),
20650
+ serializedBody: undefined
20651
+ };
20652
+ if (opts.security) {
20653
+ await setAuthParams8({
20654
+ ...opts,
20655
+ security: opts.security
20656
+ });
20657
+ }
20658
+ if (opts.requestValidator) {
20659
+ await opts.requestValidator(opts);
20660
+ }
20661
+ if (opts.body !== undefined && opts.bodySerializer) {
20662
+ opts.serializedBody = opts.bodySerializer(opts.body);
20663
+ }
20664
+ if (opts.body === undefined || opts.serializedBody === "") {
20665
+ opts.headers.delete("Content-Type");
20666
+ }
20667
+ const resolvedOpts = opts;
20668
+ const url = buildUrl8(resolvedOpts);
20669
+ return { opts: resolvedOpts, url };
20670
+ };
20671
+ const request = async (options) => {
20672
+ const { opts, url } = await beforeRequest(options);
20673
+ const requestInit = {
20674
+ redirect: "follow",
20675
+ ...opts,
20676
+ body: getValidRequestBody8(opts)
20677
+ };
20678
+ let request2 = new Request(url, requestInit);
20679
+ for (const fn of interceptors.request.fns) {
20680
+ if (fn) {
20681
+ request2 = await fn(request2, opts);
20682
+ }
20683
+ }
20684
+ const _fetch = opts.fetch;
20685
+ let response;
20686
+ try {
20687
+ response = await _fetch(request2);
20688
+ } catch (error2) {
20689
+ let finalError2 = error2;
20690
+ for (const fn of interceptors.error.fns) {
20691
+ if (fn) {
20692
+ finalError2 = await fn(error2, undefined, request2, opts);
20693
+ }
20694
+ }
20695
+ finalError2 = finalError2 || {};
20696
+ if (opts.throwOnError) {
20697
+ throw finalError2;
20698
+ }
20699
+ return opts.responseStyle === "data" ? undefined : {
20700
+ error: finalError2,
20701
+ request: request2,
20702
+ response: undefined
20703
+ };
20704
+ }
20705
+ for (const fn of interceptors.response.fns) {
20706
+ if (fn) {
20707
+ response = await fn(response, request2, opts);
20708
+ }
20709
+ }
20710
+ const result = {
20711
+ request: request2,
20712
+ response
20713
+ };
20714
+ if (response.ok) {
20715
+ const parseAs = (opts.parseAs === "auto" ? getParseAs8(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
20716
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
20717
+ let emptyData;
20718
+ switch (parseAs) {
20719
+ case "arrayBuffer":
20720
+ case "blob":
20721
+ case "text":
20722
+ emptyData = await response[parseAs]();
20723
+ break;
20724
+ case "formData":
20725
+ emptyData = new FormData;
20726
+ break;
20727
+ case "stream":
20728
+ emptyData = response.body;
20729
+ break;
20730
+ case "json":
20731
+ default:
20732
+ emptyData = {};
20733
+ break;
20734
+ }
20735
+ return opts.responseStyle === "data" ? emptyData : {
20736
+ data: emptyData,
20737
+ ...result
20738
+ };
20739
+ }
20740
+ let data;
20741
+ switch (parseAs) {
20742
+ case "arrayBuffer":
20743
+ case "blob":
20744
+ case "formData":
20745
+ case "text":
20746
+ data = await response[parseAs]();
20747
+ break;
20748
+ case "json": {
20749
+ const text = await response.text();
20750
+ data = text ? JSON.parse(text) : {};
20751
+ break;
20752
+ }
20753
+ case "stream":
20754
+ return opts.responseStyle === "data" ? response.body : {
20755
+ data: response.body,
20756
+ ...result
20757
+ };
20758
+ }
20759
+ if (parseAs === "json") {
20760
+ if (opts.responseValidator) {
20761
+ await opts.responseValidator(data);
20762
+ }
20763
+ if (opts.responseTransformer) {
20764
+ data = await opts.responseTransformer(data);
20765
+ }
20766
+ }
20767
+ return opts.responseStyle === "data" ? data : {
20768
+ data,
20769
+ ...result
20770
+ };
20771
+ }
20772
+ const textError = await response.text();
20773
+ let jsonError;
20774
+ try {
20775
+ jsonError = JSON.parse(textError);
20776
+ } catch {}
20777
+ const error = jsonError ?? textError;
20778
+ let finalError = error;
20779
+ for (const fn of interceptors.error.fns) {
20780
+ if (fn) {
20781
+ finalError = await fn(error, response, request2, opts);
20782
+ }
20783
+ }
20784
+ finalError = finalError || {};
20785
+ if (opts.throwOnError) {
20786
+ throw finalError;
20787
+ }
20788
+ return opts.responseStyle === "data" ? undefined : {
20789
+ error: finalError,
20790
+ ...result
20791
+ };
20792
+ };
20793
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
20794
+ const makeSseFn = (method) => async (options) => {
20795
+ const { opts, url } = await beforeRequest(options);
20796
+ return createSseClient8({
20797
+ ...opts,
20798
+ body: opts.body,
20799
+ headers: opts.headers,
20800
+ method,
20801
+ onRequest: async (url2, init2) => {
20802
+ let request2 = new Request(url2, init2);
20803
+ for (const fn of interceptors.request.fns) {
20804
+ if (fn) {
20805
+ request2 = await fn(request2, opts);
20806
+ }
20807
+ }
20808
+ return request2;
20809
+ },
20810
+ serializedBody: getValidRequestBody8(opts),
20811
+ url
20812
+ });
20813
+ };
20814
+ const _buildUrl = (options) => buildUrl8({ ..._config, ...options });
20815
+ return {
20816
+ buildUrl: _buildUrl,
20817
+ connect: makeMethodFn("CONNECT"),
20818
+ delete: makeMethodFn("DELETE"),
20819
+ get: makeMethodFn("GET"),
20820
+ getConfig,
20821
+ head: makeMethodFn("HEAD"),
20822
+ interceptors,
20823
+ options: makeMethodFn("OPTIONS"),
20824
+ patch: makeMethodFn("PATCH"),
20825
+ post: makeMethodFn("POST"),
20826
+ put: makeMethodFn("PUT"),
20827
+ request,
20828
+ setConfig,
20829
+ sse: {
20830
+ connect: makeSseFn("CONNECT"),
20831
+ delete: makeSseFn("DELETE"),
20832
+ get: makeSseFn("GET"),
20833
+ head: makeSseFn("HEAD"),
20834
+ options: makeSseFn("OPTIONS"),
20835
+ patch: makeSseFn("PATCH"),
20836
+ post: makeSseFn("POST"),
20837
+ put: makeSseFn("PUT"),
20838
+ trace: makeSseFn("TRACE")
20839
+ },
20840
+ trace: makeMethodFn("TRACE")
20841
+ };
20842
+ };
20843
+ var init_client_gen15 = __esm(() => {
20844
+ init_utils_gen15();
20845
+ init_utils_gen16();
20846
+ });
20847
+
20848
+ // src/generated/seerr/client/index.ts
20849
+ var init_client9 = __esm(() => {
20850
+ init_client_gen15();
20851
+ init_utils_gen16();
20852
+ });
20853
+
20854
+ // src/generated/seerr/client.gen.ts
20855
+ var client8;
20856
+ var init_client_gen16 = __esm(() => {
20857
+ init_client9();
20858
+ client8 = createClient8(createConfig8());
20859
+ });
20860
+
20861
+ // src/generated/seerr/sdk.gen.ts
20862
+ var getStatus = (options) => (options?.client ?? client8).get({ url: "/status", ...options }), getUser = (options) => (options?.client ?? client8).get({
20863
+ security: [{
20864
+ in: "cookie",
20865
+ name: "connect.sid",
20866
+ type: "apiKey"
20867
+ }, { name: "X-Api-Key", type: "apiKey" }],
20868
+ url: "/user",
20869
+ ...options
20870
+ }), getUserByUserId = (options) => (options.client ?? client8).get({
20871
+ security: [{
20872
+ in: "cookie",
20873
+ name: "connect.sid",
20874
+ type: "apiKey"
20875
+ }, { name: "X-Api-Key", type: "apiKey" }],
20876
+ url: "/user/{userId}",
20877
+ ...options
20878
+ }), getSearch = (options) => (options.client ?? client8).get({
20879
+ security: [{
20880
+ in: "cookie",
20881
+ name: "connect.sid",
20882
+ type: "apiKey"
20883
+ }, { name: "X-Api-Key", type: "apiKey" }],
20884
+ url: "/search",
20885
+ ...options
20886
+ }), getRequest = (options) => (options?.client ?? client8).get({
20887
+ security: [{
20888
+ in: "cookie",
20889
+ name: "connect.sid",
20890
+ type: "apiKey"
20891
+ }, { name: "X-Api-Key", type: "apiKey" }],
20892
+ url: "/request",
20893
+ ...options
20894
+ }), getRequestCount = (options) => (options?.client ?? client8).get({
20895
+ security: [{
20896
+ in: "cookie",
20897
+ name: "connect.sid",
20898
+ type: "apiKey"
20899
+ }, { name: "X-Api-Key", type: "apiKey" }],
20900
+ url: "/request/count",
20901
+ ...options
20902
+ }), getRequestByRequestId = (options) => (options.client ?? client8).get({
20903
+ security: [{
20904
+ in: "cookie",
20905
+ name: "connect.sid",
20906
+ type: "apiKey"
20907
+ }, { name: "X-Api-Key", type: "apiKey" }],
20908
+ url: "/request/{requestId}",
20909
+ ...options
20910
+ }), postRequestByRequestIdByStatus = (options) => (options.client ?? client8).post({
20911
+ security: [{
20912
+ in: "cookie",
20913
+ name: "connect.sid",
20914
+ type: "apiKey"
20915
+ }, { name: "X-Api-Key", type: "apiKey" }],
20916
+ url: "/request/{requestId}/{status}",
20917
+ ...options
20918
+ }), getMedia = (options) => (options?.client ?? client8).get({
20919
+ security: [{
20920
+ in: "cookie",
20921
+ name: "connect.sid",
20922
+ type: "apiKey"
20923
+ }, { name: "X-Api-Key", type: "apiKey" }],
20924
+ url: "/media",
20925
+ ...options
20926
+ });
20927
+ var init_sdk_gen8 = __esm(() => {
20928
+ init_client_gen16();
20929
+ });
20930
+
20931
+ // src/generated/seerr/index.ts
20932
+ var init_seerr = __esm(() => {
20933
+ init_sdk_gen8();
20934
+ });
20935
+
20936
+ // src/clients/seerr.ts
20937
+ var exports_seerr = {};
20938
+ __export(exports_seerr, {
20939
+ SeerrClient: () => SeerrClient
20940
+ });
20941
+
20942
+ class SeerrClient {
20943
+ clientConfig;
20944
+ constructor(config) {
20945
+ this.clientConfig = createServarrClient(config);
20946
+ client8.setConfig({
20947
+ baseUrl: `${this.clientConfig.getBaseUrl()}/api/v1`,
20948
+ headers: {
20949
+ "X-Api-Key": this.clientConfig.config.apiKey,
20950
+ ...this.clientConfig.config.headers ?? {}
20951
+ }
20952
+ });
20953
+ }
20954
+ async getSystemStatus() {
20955
+ return getStatus();
20956
+ }
20957
+ async getRequests(options) {
20958
+ const query = {};
20959
+ if (options?.take)
20960
+ query.take = options.take;
20961
+ if (options?.skip)
20962
+ query.skip = options.skip;
20963
+ if (options?.filter)
20964
+ query.filter = options.filter;
20965
+ if (options?.sort)
20966
+ query.sort = options.sort;
20967
+ if (options?.sortDirection)
20968
+ query.sortDirection = options.sortDirection;
20969
+ return getRequest(Object.keys(query).length > 0 ? { query } : {});
20970
+ }
20971
+ async getRequestById(requestId) {
20972
+ return getRequestByRequestId({ path: { requestId } });
20973
+ }
20974
+ async getRequestCount() {
20975
+ return getRequestCount();
20976
+ }
20977
+ async approveRequest(requestId) {
20978
+ const result = await postRequestByRequestIdByStatus({
20979
+ path: { requestId, status: "approve" }
20980
+ });
20981
+ return result.data;
20982
+ }
20983
+ async declineRequest(requestId) {
20984
+ const result = await postRequestByRequestIdByStatus({
20985
+ path: { requestId, status: "decline" }
20986
+ });
20987
+ return result.data;
20988
+ }
20989
+ async search(query, page, language) {
20990
+ const searchQuery = { query };
20991
+ if (page)
20992
+ searchQuery.page = page;
20993
+ if (language)
20994
+ searchQuery.language = language;
20995
+ return getSearch({ query: searchQuery });
20996
+ }
20997
+ async getUsers(options) {
20998
+ const query = {};
20999
+ if (options?.take)
21000
+ query.take = options.take;
21001
+ if (options?.skip)
21002
+ query.skip = options.skip;
21003
+ if (options?.sort)
21004
+ query.sort = options.sort;
21005
+ return getUser(Object.keys(query).length > 0 ? { query } : {});
21006
+ }
21007
+ async getUserById(userId) {
21008
+ return getUserByUserId({ path: { userId } });
21009
+ }
21010
+ async getMedia(options) {
21011
+ const query = {};
21012
+ if (options?.take)
21013
+ query.take = options.take;
21014
+ if (options?.skip)
21015
+ query.skip = options.skip;
21016
+ return getMedia(Object.keys(query).length > 0 ? { query } : {});
21017
+ }
21018
+ updateConfig(newConfig) {
21019
+ const updatedConfig = { ...this.clientConfig.config, ...newConfig };
21020
+ this.clientConfig = createServarrClient(updatedConfig);
21021
+ client8.setConfig({
21022
+ baseUrl: `${this.clientConfig.getBaseUrl()}/api/v1`,
21023
+ headers: {
21024
+ "X-Api-Key": this.clientConfig.config.apiKey,
21025
+ ...this.clientConfig.config.headers ?? {}
21026
+ }
21027
+ });
21028
+ return this.clientConfig.config;
21029
+ }
21030
+ }
21031
+ var init_seerr2 = __esm(() => {
21032
+ init_client();
21033
+ init_client_gen16();
21034
+ init_seerr();
21035
+ });
21036
+
21037
+ // src/cli/commands/seerr.ts
21038
+ var exports_seerr3 = {};
21039
+ __export(exports_seerr3, {
21040
+ seerr: () => seerr,
21041
+ resources: () => resources8
21042
+ });
21043
+ var resources8, seerr;
21044
+ var init_seerr3 = __esm(() => {
21045
+ init_seerr2();
21046
+ init_service();
21047
+ resources8 = [
21048
+ {
21049
+ name: "requests",
21050
+ description: "Manage media requests",
21051
+ actions: [
21052
+ {
21053
+ name: "list",
21054
+ description: "List media requests",
21055
+ args: [
21056
+ {
21057
+ name: "filter",
21058
+ description: "Filter (all|approved|available|pending|processing|unavailable|failed|deleted|completed)"
21059
+ }
21060
+ ],
21061
+ columns: ["id", "status", "requestedBy", "createdAt", "updatedAt"],
21062
+ idField: "id",
21063
+ run: (c3, a2) => c3.getRequests(a2.filter ? { filter: a2.filter } : undefined)
21064
+ },
21065
+ {
21066
+ name: "count",
21067
+ description: "Get request counts",
21068
+ run: (c3) => c3.getRequestCount()
21069
+ },
21070
+ {
21071
+ name: "approve",
21072
+ description: "Approve a request",
21073
+ args: [
21074
+ {
21075
+ name: "id",
21076
+ description: "Request ID",
21077
+ required: true
21078
+ }
21079
+ ],
21080
+ run: (c3, a2) => c3.approveRequest(a2.id)
21081
+ },
21082
+ {
21083
+ name: "decline",
21084
+ description: "Decline a request",
21085
+ args: [
21086
+ {
21087
+ name: "id",
21088
+ description: "Request ID",
21089
+ required: true
21090
+ }
21091
+ ],
21092
+ confirmMessage: "Are you sure you want to decline this request?",
21093
+ run: (c3, a2) => c3.declineRequest(a2.id)
21094
+ }
21095
+ ]
21096
+ },
21097
+ {
21098
+ name: "search",
21099
+ description: "Search media",
21100
+ actions: [
21101
+ {
21102
+ name: "query",
21103
+ description: "Search for movies and TV shows",
21104
+ args: [
21105
+ {
21106
+ name: "query",
21107
+ description: "Search query",
21108
+ required: true
21109
+ }
21110
+ ],
21111
+ columns: ["id", "mediaType", "title", "releaseDate", "voteAverage"],
21112
+ idField: "id",
21113
+ run: (c3, a2) => c3.search(a2.query)
21114
+ }
21115
+ ]
21116
+ },
21117
+ {
21118
+ name: "users",
21119
+ description: "Manage users",
21120
+ actions: [
21121
+ {
21122
+ name: "list",
21123
+ description: "List users",
21124
+ columns: ["id", "email", "username", "requestCount", "createdAt"],
21125
+ idField: "id",
21126
+ run: (c3) => c3.getUsers()
21127
+ }
21128
+ ]
21129
+ },
21130
+ {
21131
+ name: "status",
21132
+ description: "Server status",
21133
+ actions: [
21134
+ {
21135
+ name: "show",
21136
+ description: "Show server status",
21137
+ columns: ["version", "commitTag", "updateAvailable", "commitsBehind"],
21138
+ run: (c3) => c3.getSystemStatus()
21139
+ }
21140
+ ]
21141
+ }
21142
+ ];
21143
+ seerr = buildServiceCommand("seerr", "Manage Seerr (Media Requests)", (config) => new SeerrClient(config), resources8);
21144
+ });
21145
+
21146
+ // src/cli/commands/doctor.ts
21147
+ var exports_doctor = {};
21148
+ __export(exports_doctor, {
21149
+ doctor: () => doctor
21150
+ });
21151
+ function classifyError(error) {
21152
+ if (!(error instanceof Error))
21153
+ return "Unknown error";
21154
+ const msg = error.message;
21155
+ const cause = error.cause;
21156
+ if (cause?.code === "ECONNREFUSED" || msg.includes("ECONNREFUSED")) {
21157
+ return "Connection refused - is the service running?";
21158
+ }
21159
+ if (cause?.code === "ENOTFOUND" || msg.includes("ENOTFOUND")) {
21160
+ return "Host not found - check the URL";
21161
+ }
21162
+ if (cause?.code === "ECONNRESET" || msg.includes("ECONNRESET")) {
21163
+ return "Connection reset - service may have crashed";
21164
+ }
21165
+ if (cause?.code === "ETIMEDOUT" || msg.includes("ETIMEDOUT") || msg.includes("timed out")) {
21166
+ return "Connection timed out - service may be unreachable";
21167
+ }
21168
+ if (msg.includes("fetch failed") || msg.includes("Failed to fetch")) {
21169
+ return `Service unreachable - ${cause?.message ?? "check URL and network"}`;
21170
+ }
21171
+ if (msg.includes("401") || msg.includes("Unauthorized")) {
21172
+ return "Authentication failed (401) - check your API key";
21173
+ }
21174
+ if (msg.includes("403") || msg.includes("Forbidden")) {
21175
+ return "Access denied (403) - check your API key permissions";
21176
+ }
21177
+ if (msg.includes("502") || msg.includes("Bad Gateway")) {
21178
+ return "Bad gateway (502) - reverse proxy or service issue";
21179
+ }
21180
+ if (msg.includes("503") || msg.includes("Service Unavailable")) {
21181
+ return "Service unavailable (503) - service may be starting up";
21182
+ }
21183
+ if (msg.includes("CERT") || msg.includes("certificate") || msg.includes("SSL")) {
21184
+ return "SSL/TLS certificate error - check HTTPS configuration";
20106
21185
  }
20107
21186
  return msg;
20108
21187
  }
@@ -20114,7 +21193,7 @@ function extractVersion(service, status) {
20114
21193
  if (service === "bazarr") {
20115
21194
  return data?.data?.bazarr_version ?? data?.bazarr_version ?? null;
20116
21195
  }
20117
- if (service === "qbittorrent") {
21196
+ if (service === "qbittorrent" || service === "seerr") {
20118
21197
  return data?.version ?? null;
20119
21198
  }
20120
21199
  return data?.version ?? status?.version ?? null;
@@ -20129,6 +21208,7 @@ var init_doctor = __esm(() => {
20129
21208
  init_qbittorrent2();
20130
21209
  init_radarr2();
20131
21210
  init_readarr2();
21211
+ init_seerr2();
20132
21212
  init_sonarr2();
20133
21213
  init_config();
20134
21214
  init_output();
@@ -20139,7 +21219,8 @@ var init_doctor = __esm(() => {
20139
21219
  readarr: (c3) => new ReadarrClient(c3),
20140
21220
  prowlarr: (c3) => new ProwlarrClient(c3),
20141
21221
  bazarr: (c3) => new BazarrClient(c3),
20142
- qbittorrent: (c3) => new QBittorrentClient(c3)
21222
+ qbittorrent: (c3) => new QBittorrentClient(c3),
21223
+ seerr: (c3) => new SeerrClient(c3)
20143
21224
  };
20144
21225
  doctor = defineCommand({
20145
21226
  meta: {
@@ -20184,8 +21265,8 @@ var init_doctor = __esm(() => {
20184
21265
  });
20185
21266
  continue;
20186
21267
  }
20187
- const client8 = factory(svcConfig);
20188
- const status = await client8.getSystemStatus();
21268
+ const client9 = factory(svcConfig);
21269
+ const status = await client9.getSystemStatus();
20189
21270
  const version = extractVersion(service, status) ?? "?";
20190
21271
  if (version === "?") {
20191
21272
  throw new Error("Unexpected response payload");
@@ -20213,7 +21294,7 @@ var init_doctor = __esm(() => {
20213
21294
  }
20214
21295
  formatOutput(results, {
20215
21296
  format,
20216
- columns: ["service", "status", "version", "baseUrl", "error"],
21297
+ columns: ["service", "status", "configured", "version", "baseUrl", "error"],
20217
21298
  idField: "service",
20218
21299
  select: args.select
20219
21300
  });
@@ -20242,7 +21323,8 @@ var init_config2 = __esm(() => {
20242
21323
  readarr: 8787,
20243
21324
  prowlarr: 9696,
20244
21325
  bazarr: 6767,
20245
- qbittorrent: 8080
21326
+ qbittorrent: 8080,
21327
+ seerr: 5055
20246
21328
  };
20247
21329
  configInit = defineCommand({
20248
21330
  meta: {
@@ -20274,8 +21356,8 @@ var init_config2 = __esm(() => {
20274
21356
  config.services[service] = { baseUrl, username, password };
20275
21357
  try {
20276
21358
  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();
21359
+ const client9 = new QBittorrentClient2({ baseUrl, username, password });
21360
+ const status = await client9.getSystemStatus();
20279
21361
  consola.success(`Connected to ${service} v${status.version}`);
20280
21362
  } catch {
20281
21363
  consola.warn(`Could not connect to ${service} — config saved anyway.`);
@@ -20290,17 +21372,19 @@ var init_config2 = __esm(() => {
20290
21372
  const { ReadarrClient: ReadarrClient2 } = await Promise.resolve().then(() => (init_readarr2(), exports_readarr));
20291
21373
  const { ProwlarrClient: ProwlarrClient2 } = await Promise.resolve().then(() => (init_prowlarr2(), exports_prowlarr));
20292
21374
  const { BazarrClient: BazarrClient2 } = await Promise.resolve().then(() => (init_bazarr2(), exports_bazarr));
21375
+ const { SeerrClient: SeerrClient2 } = await Promise.resolve().then(() => (init_seerr2(), exports_seerr));
20293
21376
  const factories = {
20294
21377
  radarr: (c3) => new RadarrClient2(c3),
20295
21378
  sonarr: (c3) => new SonarrClient2(c3),
20296
21379
  lidarr: (c3) => new LidarrClient2(c3),
20297
21380
  readarr: (c3) => new ReadarrClient2(c3),
20298
21381
  prowlarr: (c3) => new ProwlarrClient2(c3),
20299
- bazarr: (c3) => new BazarrClient2(c3)
21382
+ bazarr: (c3) => new BazarrClient2(c3),
21383
+ seerr: (c3) => new SeerrClient2(c3)
20300
21384
  };
20301
- const client8 = factories[service]?.(config.services[service]);
20302
- if (client8) {
20303
- const status = await client8.getSystemStatus();
21385
+ const client9 = factories[service]?.(config.services[service]);
21386
+ if (client9) {
21387
+ const status = await client9.getSystemStatus();
20304
21388
  const version = status?.data?.version ?? status?.version ?? "?";
20305
21389
  consola.success(`Connected to ${service} v${version}`);
20306
21390
  }
@@ -20402,11 +21486,11 @@ __export(exports_completions, {
20402
21486
  function generateBashCompletion() {
20403
21487
  const services = Object.keys(SERVICE_COMMANDS).join(" ");
20404
21488
  const globals = "doctor config completions";
20405
- const resourceVars = Object.entries(SERVICE_COMMANDS).map(([svc, resources8]) => ` local ${svc}_resources="${Object.keys(resources8).join(" ")}"`).join(`
21489
+ const resourceVars = Object.entries(SERVICE_COMMANDS).map(([svc, resources9]) => ` local ${svc}_resources="${Object.keys(resources9).join(" ")}"`).join(`
20406
21490
  `);
20407
21491
  const resourceCases = Object.keys(SERVICE_COMMANDS).map((svc) => ` ${svc}) COMPREPLY=( $(compgen -W "$${svc}_resources" -- "$cur") ) ;;`).join(`
20408
21492
  `);
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(`
21493
+ const actionCases = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources9]) => Object.entries(resources9).map(([res, actions]) => ` ${res}) [[ "\${COMP_WORDS[1]}" == "${svc}" ]] && COMPREPLY=( $(compgen -W "${actions.join(" ")}" -- "$cur") ) ;;`)).join(`
20410
21494
  `);
20411
21495
  return `#!/bin/bash
20412
21496
  _tsarr_completions() {
@@ -20440,9 +21524,9 @@ complete -F _tsarr_completions tsarr`;
20440
21524
  }
20441
21525
  function generateZshCompletion() {
20442
21526
  const services = Object.keys(SERVICE_COMMANDS).join(" ");
20443
- const resourceAssoc = Object.entries(SERVICE_COMMANDS).map(([svc, resources8]) => ` ${svc} "${Object.keys(resources8).join(" ")}"`).join(`
21527
+ const resourceAssoc = Object.entries(SERVICE_COMMANDS).map(([svc, resources9]) => ` ${svc} "${Object.keys(resources9).join(" ")}"`).join(`
20444
21528
  `);
20445
- const actionAssoc = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources8]) => Object.entries(resources8).map(([res, actions]) => ` ${svc}:${res} "${actions.join(" ")}"`)).join(`
21529
+ const actionAssoc = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources9]) => Object.entries(resources9).map(([res, actions]) => ` ${svc}:${res} "${actions.join(" ")}"`)).join(`
20446
21530
  `);
20447
21531
  return `#compdef tsarr
20448
21532
 
@@ -20499,12 +21583,12 @@ _tsarr "$@"`;
20499
21583
  function generateFishCompletion() {
20500
21584
  const services = Object.keys(SERVICE_COMMANDS).join(" ");
20501
21585
  const globals = "doctor config completions";
20502
- const resourceCompletions = Object.entries(SERVICE_COMMANDS).map(([svc, resources8]) => {
20503
- const res = Object.keys(resources8).join(" ");
21586
+ const resourceCompletions = Object.entries(SERVICE_COMMANDS).map(([svc, resources9]) => {
21587
+ const res = Object.keys(resources9).join(" ");
20504
21588
  return `complete -c tsarr -n "__fish_seen_subcommand_from ${svc}; and not __fish_seen_subcommand_from ${res}" -a "${res}"`;
20505
21589
  }).join(`
20506
21590
  `);
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(`
21591
+ const actionCompletions = Object.entries(SERVICE_COMMANDS).flatMap(([svc, resources9]) => Object.entries(resources9).map(([res, actions]) => `complete -c tsarr -n "__fish_seen_subcommand_from ${svc}; and __fish_seen_subcommand_from ${res}; and not __fish_seen_subcommand_from ${actions.join(" ")}" -a "${actions.join(" ")}"`)).join(`
20508
21592
  `);
20509
21593
  return `# Fish completions for tsarr
20510
21594
  set -l services ${services}
@@ -20581,6 +21665,12 @@ var init_completions = __esm(() => {
20581
21665
  provider: ["list"],
20582
21666
  language: ["list", "profiles"],
20583
21667
  system: ["status", "health", "badges"]
21668
+ },
21669
+ seerr: {
21670
+ requests: ["list", "count", "approve", "decline"],
21671
+ search: ["query"],
21672
+ users: ["list"],
21673
+ status: ["show"]
20584
21674
  }
20585
21675
  };
20586
21676
  completions = defineCommand({
@@ -20619,7 +21709,7 @@ init_dist();
20619
21709
  // package.json
20620
21710
  var package_default = {
20621
21711
  name: "tsarr",
20622
- version: "2.6.0",
21712
+ version: "2.7.1",
20623
21713
  author: "Robbe Verhelst",
20624
21714
  repository: {
20625
21715
  type: "git",
@@ -20675,6 +21765,10 @@ var package_default = {
20675
21765
  import: "./dist/clients/qbittorrent.js",
20676
21766
  types: "./dist/clients/qbittorrent.d.ts"
20677
21767
  },
21768
+ "./seerr": {
21769
+ import: "./dist/clients/seerr.js",
21770
+ types: "./dist/clients/seerr.d.ts"
21771
+ },
20678
21772
  "./radarr/types": {
20679
21773
  types: "./dist/clients/radarr-types.d.ts"
20680
21774
  },
@@ -20695,6 +21789,9 @@ var package_default = {
20695
21789
  },
20696
21790
  "./qbittorrent/types": {
20697
21791
  types: "./dist/clients/qbittorrent-types.d.ts"
21792
+ },
21793
+ "./seerr/types": {
21794
+ types: "./dist/clients/seerr-types.d.ts"
20698
21795
  }
20699
21796
  },
20700
21797
  description: "Type-safe TypeScript SDK for Servarr APIs (Radarr, Sonarr, etc.)",
@@ -20714,6 +21811,9 @@ var package_default = {
20714
21811
  "prowlarr",
20715
21812
  "bazarr",
20716
21813
  "qbittorrent",
21814
+ "seerr",
21815
+ "jellyseerr",
21816
+ "overseerr",
20717
21817
  "typescript",
20718
21818
  "sdk",
20719
21819
  "api",
@@ -20727,7 +21827,7 @@ var package_default = {
20727
21827
  },
20728
21828
  scripts: {
20729
21829
  build: "bun run generate && bun run generate:types && bun run build:js && bun run build:cli && bun run build:types",
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",
21830
+ "build:js": "bun build src/index.ts --outdir dist --target node --minify --splitting && bun build src/clients/radarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/sonarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/lidarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/readarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/prowlarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/bazarr.ts --outdir dist/clients --target node --format esm && bun build src/clients/qbittorrent.ts --outdir dist/clients --target node --format esm && bun build src/clients/seerr.ts --outdir dist/clients --target node --format esm",
20731
21831
  "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target node --format esm && chmod +x dist/cli/index.js",
20732
21832
  "build:types": "tsc --project tsconfig.build.json",
20733
21833
  prepublishOnly: "bun run build",
@@ -20765,7 +21865,7 @@ var main = defineCommand({
20765
21865
  meta: {
20766
21866
  name: "tsarr",
20767
21867
  version,
20768
- description: "Type-safe CLI for Servarr APIs (Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr, qBittorrent)"
21868
+ description: "Type-safe CLI for Servarr APIs (Radarr, Sonarr, Lidarr, Readarr, Prowlarr, Bazarr, qBittorrent, Seerr)"
20769
21869
  },
20770
21870
  subCommands: {
20771
21871
  radarr: () => Promise.resolve().then(() => (init_radarr3(), exports_radarr3)).then((m2) => m2.radarr),
@@ -20775,6 +21875,7 @@ var main = defineCommand({
20775
21875
  prowlarr: () => Promise.resolve().then(() => (init_prowlarr3(), exports_prowlarr3)).then((m2) => m2.prowlarr),
20776
21876
  bazarr: () => Promise.resolve().then(() => (init_bazarr3(), exports_bazarr3)).then((m2) => m2.bazarr),
20777
21877
  qbit: () => Promise.resolve().then(() => (init_qbit(), exports_qbit)).then((m2) => m2.qbit),
21878
+ seerr: () => Promise.resolve().then(() => (init_seerr3(), exports_seerr3)).then((m2) => m2.seerr),
20778
21879
  doctor: () => Promise.resolve().then(() => (init_doctor(), exports_doctor)).then((m2) => m2.doctor),
20779
21880
  config: () => Promise.resolve().then(() => (init_config2(), exports_config)).then((m2) => m2.config),
20780
21881
  completions: () => Promise.resolve().then(() => (init_completions(), exports_completions)).then((m2) => m2.completions)