tsarr 1.0.0 → 1.1.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.
@@ -0,0 +1,432 @@
1
+ // src/core/errors.ts
2
+ class TsArrError extends Error {
3
+ code;
4
+ statusCode;
5
+ details;
6
+ constructor(message, code, statusCode, details) {
7
+ super(message);
8
+ this.code = code;
9
+ this.statusCode = statusCode;
10
+ this.details = details;
11
+ this.name = "TsArrError";
12
+ }
13
+ }
14
+
15
+ class ApiKeyError extends TsArrError {
16
+ constructor(message = "Invalid or missing API key") {
17
+ super(message, "API_KEY_ERROR", 401);
18
+ this.name = "ApiKeyError";
19
+ }
20
+ }
21
+
22
+ class ConnectionError extends TsArrError {
23
+ constructor(message, details) {
24
+ super(message, "CONNECTION_ERROR", undefined, details);
25
+ this.name = "ConnectionError";
26
+ }
27
+ }
28
+
29
+ // src/core/client.ts
30
+ function createServarrClient(config) {
31
+ if (!config.apiKey) {
32
+ throw new ApiKeyError;
33
+ }
34
+ if (!config.baseUrl) {
35
+ throw new ConnectionError("No base URL provided");
36
+ }
37
+ const validatedConfig = {
38
+ ...config,
39
+ baseUrl: config.baseUrl.replace(/\/$/, "")
40
+ };
41
+ return {
42
+ config: validatedConfig,
43
+ getHeaders: () => ({
44
+ "X-Api-Key": validatedConfig.apiKey,
45
+ "Content-Type": "application/json",
46
+ ...validatedConfig.headers
47
+ }),
48
+ getBaseUrl: () => validatedConfig.baseUrl
49
+ };
50
+ }
51
+
52
+ // node_modules/@hey-api/client-fetch/dist/index.js
53
+ var T = /\{[^{}]+\}/g;
54
+ var h = ({ allowReserved: i, name: n, value: e }) => {
55
+ if (e == null)
56
+ return "";
57
+ if (typeof e == "object")
58
+ throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
59
+ return `${n}=${i ? e : encodeURIComponent(e)}`;
60
+ };
61
+ var U = (i) => {
62
+ switch (i) {
63
+ case "label":
64
+ return ".";
65
+ case "matrix":
66
+ return ";";
67
+ case "simple":
68
+ return ",";
69
+ default:
70
+ return "&";
71
+ }
72
+ };
73
+ var $ = (i) => {
74
+ switch (i) {
75
+ case "form":
76
+ return ",";
77
+ case "pipeDelimited":
78
+ return "|";
79
+ case "spaceDelimited":
80
+ return "%20";
81
+ default:
82
+ return ",";
83
+ }
84
+ };
85
+ var D = (i) => {
86
+ switch (i) {
87
+ case "label":
88
+ return ".";
89
+ case "matrix":
90
+ return ";";
91
+ case "simple":
92
+ return ",";
93
+ default:
94
+ return "&";
95
+ }
96
+ };
97
+ var j = ({ allowReserved: i, explode: n, name: e, style: a, value: o }) => {
98
+ if (!n) {
99
+ let r = (i ? o : o.map((c) => encodeURIComponent(c))).join($(a));
100
+ switch (a) {
101
+ case "label":
102
+ return `.${r}`;
103
+ case "matrix":
104
+ return `;${e}=${r}`;
105
+ case "simple":
106
+ return r;
107
+ default:
108
+ return `${e}=${r}`;
109
+ }
110
+ }
111
+ let s = U(a), t = o.map((r) => a === "label" || a === "simple" ? i ? r : encodeURIComponent(r) : h({ allowReserved: i, name: e, value: r })).join(s);
112
+ return a === "label" || a === "matrix" ? s + t : t;
113
+ };
114
+ var C = ({ allowReserved: i, explode: n, name: e, style: a, value: o }) => {
115
+ if (o instanceof Date)
116
+ return `${e}=${o.toISOString()}`;
117
+ if (a !== "deepObject" && !n) {
118
+ let r = [];
119
+ Object.entries(o).forEach(([u, l]) => {
120
+ r = [...r, u, i ? l : encodeURIComponent(l)];
121
+ });
122
+ let c = r.join(",");
123
+ switch (a) {
124
+ case "form":
125
+ return `${e}=${c}`;
126
+ case "label":
127
+ return `.${c}`;
128
+ case "matrix":
129
+ return `;${e}=${c}`;
130
+ default:
131
+ return c;
132
+ }
133
+ }
134
+ let s = D(a), t = Object.entries(o).map(([r, c]) => h({ allowReserved: i, name: a === "deepObject" ? `${e}[${r}]` : r, value: c })).join(s);
135
+ return a === "label" || a === "matrix" ? s + t : t;
136
+ };
137
+ var _ = ({ path: i, url: n }) => {
138
+ let e = n, a = n.match(T);
139
+ if (a)
140
+ for (let o of a) {
141
+ let s = false, t = o.substring(1, o.length - 1), r = "simple";
142
+ t.endsWith("*") && (s = true, t = t.substring(0, t.length - 1)), t.startsWith(".") ? (t = t.substring(1), r = "label") : t.startsWith(";") && (t = t.substring(1), r = "matrix");
143
+ let c = i[t];
144
+ if (c == null)
145
+ continue;
146
+ if (Array.isArray(c)) {
147
+ e = e.replace(o, j({ explode: s, name: t, style: r, value: c }));
148
+ continue;
149
+ }
150
+ if (typeof c == "object") {
151
+ e = e.replace(o, C({ explode: s, name: t, style: r, value: c }));
152
+ continue;
153
+ }
154
+ if (r === "matrix") {
155
+ e = e.replace(o, `;${h({ name: t, value: c })}`);
156
+ continue;
157
+ }
158
+ let u = encodeURIComponent(r === "label" ? `.${c}` : c);
159
+ e = e.replace(o, u);
160
+ }
161
+ return e;
162
+ };
163
+ var b = ({ allowReserved: i, array: n, object: e } = {}) => (o) => {
164
+ let s = [];
165
+ if (o && typeof o == "object")
166
+ for (let t in o) {
167
+ let r = o[t];
168
+ if (r != null) {
169
+ if (Array.isArray(r)) {
170
+ s = [...s, j({ allowReserved: i, explode: true, name: t, style: "form", value: r, ...n })];
171
+ continue;
172
+ }
173
+ if (typeof r == "object") {
174
+ s = [...s, C({ allowReserved: i, explode: true, name: t, style: "deepObject", value: r, ...e })];
175
+ continue;
176
+ }
177
+ s = [...s, h({ allowReserved: i, name: t, value: r })];
178
+ }
179
+ }
180
+ return s.join("&");
181
+ };
182
+ var A = (i) => {
183
+ if (!i)
184
+ return;
185
+ let n = i.split(";")[0].trim();
186
+ if (n.startsWith("application/json") || n.endsWith("+json"))
187
+ return "json";
188
+ if (n === "multipart/form-data")
189
+ return "formData";
190
+ if (["application/", "audio/", "image/", "video/"].some((e) => n.startsWith(e)))
191
+ return "blob";
192
+ if (n.startsWith("text/"))
193
+ return "text";
194
+ };
195
+ var w = ({ baseUrl: i, path: n, query: e, querySerializer: a, url: o }) => {
196
+ let s = o.startsWith("/") ? o : `/${o}`, t = i + s;
197
+ n && (t = _({ path: n, url: t }));
198
+ let r = e ? a(e) : "";
199
+ return r.startsWith("?") && (r = r.substring(1)), r && (t += `?${r}`), t;
200
+ };
201
+ var R = (i, n) => {
202
+ let e = { ...i, ...n };
203
+ return e.baseUrl?.endsWith("/") && (e.baseUrl = e.baseUrl.substring(0, e.baseUrl.length - 1)), e.headers = O(i.headers, n.headers), e;
204
+ };
205
+ var O = (...i) => {
206
+ let n = new Headers;
207
+ for (let e of i) {
208
+ if (!e || typeof e != "object")
209
+ continue;
210
+ let a = e instanceof Headers ? e.entries() : Object.entries(e);
211
+ for (let [o, s] of a)
212
+ if (s === null)
213
+ n.delete(o);
214
+ else if (Array.isArray(s))
215
+ for (let t of s)
216
+ n.append(o, t);
217
+ else
218
+ s !== undefined && n.set(o, typeof s == "object" ? JSON.stringify(s) : s);
219
+ }
220
+ return n;
221
+ };
222
+ var y = class {
223
+ _fns;
224
+ constructor() {
225
+ this._fns = [];
226
+ }
227
+ clear() {
228
+ this._fns = [];
229
+ }
230
+ exists(n) {
231
+ return this._fns.indexOf(n) !== -1;
232
+ }
233
+ eject(n) {
234
+ let e = this._fns.indexOf(n);
235
+ e !== -1 && (this._fns = [...this._fns.slice(0, e), ...this._fns.slice(e + 1)]);
236
+ }
237
+ use(n) {
238
+ this._fns = [...this._fns, n];
239
+ }
240
+ };
241
+ var P = () => ({ error: new y, request: new y, response: new y });
242
+ var E = { bodySerializer: (i) => JSON.stringify(i) };
243
+ var W = b({ allowReserved: false, array: { explode: true, style: "form" }, object: { explode: true, style: "deepObject" } });
244
+ var B = { "Content-Type": "application/json" };
245
+ var x = (i = {}) => ({ ...E, baseUrl: "", fetch: globalThis.fetch, headers: B, parseAs: "auto", querySerializer: W, ...i });
246
+ var J = (i = {}) => {
247
+ let n = R(x(), i), e = () => ({ ...n }), a = (t) => (n = R(n, t), e()), o = P(), s = async (t) => {
248
+ let r = { ...n, ...t, headers: O(n.headers, t.headers) };
249
+ r.body && r.bodySerializer && (r.body = r.bodySerializer(r.body)), r.body || r.headers.delete("Content-Type");
250
+ let c = w({ baseUrl: r.baseUrl ?? "", path: r.path, query: r.query, querySerializer: typeof r.querySerializer == "function" ? r.querySerializer : b(r.querySerializer), url: r.url }), u = { redirect: "follow", ...r }, l = new Request(c, u);
251
+ for (let f of o.request._fns)
252
+ l = await f(l, r);
253
+ let I = r.fetch, p = await I(l);
254
+ for (let f of o.response._fns)
255
+ p = await f(p, l, r);
256
+ let g = { request: l, response: p };
257
+ if (p.ok) {
258
+ if (p.status === 204 || p.headers.get("Content-Length") === "0")
259
+ return { data: {}, ...g };
260
+ if (r.parseAs === "stream")
261
+ return { data: p.body, ...g };
262
+ let f = (r.parseAs === "auto" ? A(p.headers.get("Content-Type")) : r.parseAs) ?? "json", S = await p[f]();
263
+ return f === "json" && r.responseTransformer && (S = await r.responseTransformer(S)), { data: S, ...g };
264
+ }
265
+ let m = await p.text();
266
+ try {
267
+ m = JSON.parse(m);
268
+ } catch {}
269
+ let d = m;
270
+ for (let f of o.error._fns)
271
+ d = await f(m, p, l, r);
272
+ if (d = d || {}, r.throwOnError)
273
+ throw d;
274
+ return { error: d, ...g };
275
+ };
276
+ return { connect: (t) => s({ ...t, method: "CONNECT" }), delete: (t) => s({ ...t, method: "DELETE" }), get: (t) => s({ ...t, method: "GET" }), getConfig: e, head: (t) => s({ ...t, method: "HEAD" }), interceptors: o, options: (t) => s({ ...t, method: "OPTIONS" }), patch: (t) => s({ ...t, method: "PATCH" }), post: (t) => s({ ...t, method: "POST" }), put: (t) => s({ ...t, method: "PUT" }), request: s, setConfig: a, trace: (t) => s({ ...t, method: "TRACE" }) };
277
+ };
278
+
279
+ // src/generated/readarr/services.gen.ts
280
+ var client = J(x());
281
+ var getApiV1Author = (options) => {
282
+ return (options?.client ?? client).get({
283
+ ...options,
284
+ url: "/api/v1/author"
285
+ });
286
+ };
287
+ var postApiV1Author = (options) => {
288
+ return (options?.client ?? client).post({
289
+ ...options,
290
+ url: "/api/v1/author"
291
+ });
292
+ };
293
+ var putApiV1AuthorById = (options) => {
294
+ return (options?.client ?? client).put({
295
+ ...options,
296
+ url: "/api/v1/author/{id}"
297
+ });
298
+ };
299
+ var deleteApiV1AuthorById = (options) => {
300
+ return (options?.client ?? client).delete({
301
+ ...options,
302
+ url: "/api/v1/author/{id}"
303
+ });
304
+ };
305
+ var getApiV1AuthorById = (options) => {
306
+ return (options?.client ?? client).get({
307
+ ...options,
308
+ url: "/api/v1/author/{id}"
309
+ });
310
+ };
311
+ var getApiV1AuthorLookup = (options) => {
312
+ return (options?.client ?? client).get({
313
+ ...options,
314
+ url: "/api/v1/author/lookup"
315
+ });
316
+ };
317
+ var getApiV1Book = (options) => {
318
+ return (options?.client ?? client).get({
319
+ ...options,
320
+ url: "/api/v1/book"
321
+ });
322
+ };
323
+ var getApiV1BookById = (options) => {
324
+ return (options?.client ?? client).get({
325
+ ...options,
326
+ url: "/api/v1/book/{id}"
327
+ });
328
+ };
329
+ var postApiV1Command = (options) => {
330
+ return (options?.client ?? client).post({
331
+ ...options,
332
+ url: "/api/v1/command"
333
+ });
334
+ };
335
+ var getApiV1Command = (options) => {
336
+ return (options?.client ?? client).get({
337
+ ...options,
338
+ url: "/api/v1/command"
339
+ });
340
+ };
341
+ var getApiV1Health = (options) => {
342
+ return (options?.client ?? client).get({
343
+ ...options,
344
+ url: "/api/v1/health"
345
+ });
346
+ };
347
+ var postApiV1Rootfolder = (options) => {
348
+ return (options?.client ?? client).post({
349
+ ...options,
350
+ url: "/api/v1/rootfolder"
351
+ });
352
+ };
353
+ var getApiV1Rootfolder = (options) => {
354
+ return (options?.client ?? client).get({
355
+ ...options,
356
+ url: "/api/v1/rootfolder"
357
+ });
358
+ };
359
+ var getApiV1SystemStatus = (options) => {
360
+ return (options?.client ?? client).get({
361
+ ...options,
362
+ url: "/api/v1/system/status"
363
+ });
364
+ };
365
+
366
+ // src/clients/readarr.ts
367
+ class ReadarrClient {
368
+ clientConfig;
369
+ constructor(config) {
370
+ this.clientConfig = createServarrClient(config);
371
+ client.setConfig({
372
+ baseUrl: this.clientConfig.getBaseUrl(),
373
+ headers: this.clientConfig.getHeaders()
374
+ });
375
+ }
376
+ async getSystemStatus() {
377
+ return getApiV1SystemStatus();
378
+ }
379
+ async getHealth() {
380
+ return getApiV1Health();
381
+ }
382
+ async getAuthors() {
383
+ return getApiV1Author();
384
+ }
385
+ async getAuthor(id) {
386
+ return getApiV1AuthorById({ path: { id } });
387
+ }
388
+ async addAuthor(author) {
389
+ return postApiV1Author({ body: author });
390
+ }
391
+ async updateAuthor(id, author) {
392
+ return putApiV1AuthorById({ path: { id: String(id) }, body: author });
393
+ }
394
+ async deleteAuthor(id) {
395
+ return deleteApiV1AuthorById({ path: { id } });
396
+ }
397
+ async getBooks() {
398
+ return getApiV1Book();
399
+ }
400
+ async getBook(id) {
401
+ return getApiV1BookById({ path: { id } });
402
+ }
403
+ async searchAuthors(term) {
404
+ return getApiV1AuthorLookup({ query: { term } });
405
+ }
406
+ async runCommand(command) {
407
+ return postApiV1Command({ body: command });
408
+ }
409
+ async getCommands() {
410
+ return getApiV1Command();
411
+ }
412
+ async getRootFolders() {
413
+ return getApiV1Rootfolder();
414
+ }
415
+ async addRootFolder(path) {
416
+ return postApiV1Rootfolder({
417
+ body: { path }
418
+ });
419
+ }
420
+ updateConfig(newConfig) {
421
+ const updatedConfig = { ...this.clientConfig.config, ...newConfig };
422
+ this.clientConfig = createServarrClient(updatedConfig);
423
+ client.setConfig({
424
+ baseUrl: this.clientConfig.getBaseUrl(),
425
+ headers: this.clientConfig.getHeaders()
426
+ });
427
+ return this.clientConfig.config;
428
+ }
429
+ }
430
+ export {
431
+ ReadarrClient
432
+ };