tsarr 2.10.0 → 2.11.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/LICENSE +21 -0
- package/README.md +120 -233
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/manual-import.d.ts +30 -0
- package/dist/cli/commands/manual-import.d.ts.map +1 -0
- package/dist/cli/commands/radarr.d.ts.map +1 -1
- package/dist/cli/commands/sonarr.d.ts.map +1 -1
- package/dist/cli/index.js +5200 -4854
- package/dist/cli/index.js.map +133 -0
- package/dist/clients/bazarr.d.ts +124 -124
- package/dist/clients/bazarr.js +88 -97
- package/dist/clients/bazarr.js.map +22 -0
- package/dist/clients/lidarr.d.ts +146 -146
- package/dist/clients/lidarr.js +88 -97
- package/dist/clients/lidarr.js.map +23 -0
- package/dist/clients/prowlarr.d.ts +28 -28
- package/dist/clients/prowlarr.js +88 -97
- package/dist/clients/prowlarr.js.map +23 -0
- package/dist/clients/qbittorrent.d.ts +2 -0
- package/dist/clients/qbittorrent.d.ts.map +1 -1
- package/dist/clients/qbittorrent.js +119 -102
- package/dist/clients/qbittorrent.js.map +21 -0
- package/dist/clients/radarr.d.ts +193 -149
- package/dist/clients/radarr.d.ts.map +1 -1
- package/dist/clients/radarr.js +128 -97
- package/dist/clients/radarr.js.map +23 -0
- package/dist/clients/readarr.d.ts +148 -148
- package/dist/clients/readarr.js +88 -97
- package/dist/clients/readarr.js.map +23 -0
- package/dist/clients/seerr-types.d.ts +1 -1
- package/dist/clients/seerr-types.d.ts.map +1 -1
- package/dist/clients/seerr.d.ts +16 -16
- package/dist/clients/seerr.js +88 -97
- package/dist/clients/seerr.js.map +22 -0
- package/dist/clients/sonarr.d.ts +201 -167
- package/dist/clients/sonarr.d.ts.map +1 -1
- package/dist/clients/sonarr.js +104 -107
- package/dist/clients/sonarr.js.map +23 -0
- package/dist/generated/bazarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/bazarr/client/types.gen.d.ts +5 -2
- package/dist/generated/bazarr/client/types.gen.d.ts.map +1 -1
- package/dist/generated/bazarr/client/utils.gen.d.ts +5 -1
- package/dist/generated/bazarr/client/utils.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 +5 -2
- package/dist/generated/lidarr/client/types.gen.d.ts.map +1 -1
- package/dist/generated/lidarr/client/utils.gen.d.ts +5 -1
- package/dist/generated/lidarr/client/utils.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 +5 -2
- package/dist/generated/prowlarr/client/types.gen.d.ts.map +1 -1
- package/dist/generated/prowlarr/client/utils.gen.d.ts +5 -1
- package/dist/generated/prowlarr/client/utils.gen.d.ts.map +1 -1
- package/dist/generated/qbittorrent/client/client.gen.d.ts.map +1 -1
- package/dist/generated/qbittorrent/client/types.gen.d.ts +5 -2
- package/dist/generated/qbittorrent/client/types.gen.d.ts.map +1 -1
- package/dist/generated/qbittorrent/client/utils.gen.d.ts +5 -1
- package/dist/generated/qbittorrent/client/utils.gen.d.ts.map +1 -1
- package/dist/generated/radarr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/radarr/client/types.gen.d.ts +5 -2
- package/dist/generated/radarr/client/types.gen.d.ts.map +1 -1
- package/dist/generated/radarr/client/utils.gen.d.ts +5 -1
- package/dist/generated/radarr/client/utils.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 +5 -2
- package/dist/generated/readarr/client/types.gen.d.ts.map +1 -1
- package/dist/generated/readarr/client/utils.gen.d.ts +5 -1
- package/dist/generated/readarr/client/utils.gen.d.ts.map +1 -1
- package/dist/generated/seerr/client/client.gen.d.ts.map +1 -1
- package/dist/generated/seerr/client/types.gen.d.ts +5 -2
- package/dist/generated/seerr/client/types.gen.d.ts.map +1 -1
- package/dist/generated/seerr/client/utils.gen.d.ts +5 -1
- package/dist/generated/seerr/client/utils.gen.d.ts.map +1 -1
- package/dist/generated/seerr/index.d.ts +2 -2
- package/dist/generated/seerr/index.d.ts.map +1 -1
- package/dist/generated/seerr/sdk.gen.d.ts +13 -1
- package/dist/generated/seerr/sdk.gen.d.ts.map +1 -1
- package/dist/generated/seerr/types.gen.d.ts +78 -7
- package/dist/generated/seerr/types.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 +5 -2
- package/dist/generated/sonarr/client/types.gen.d.ts.map +1 -1
- package/dist/generated/sonarr/client/utils.gen.d.ts +5 -1
- package/dist/generated/sonarr/client/utils.gen.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +12 -0
- package/dist/tsarr-2.11.0.tgz +0 -0
- package/package.json +18 -9
- package/dist/tsarr-2.10.0.tgz +0 -0
|
@@ -11,7 +11,11 @@ export declare const setAuthParams: ({ security, ...options }: Pick<Required<Req
|
|
|
11
11
|
export declare const buildUrl: Client['buildUrl'];
|
|
12
12
|
export declare const mergeConfigs: (a: Config, b: Config) => Config;
|
|
13
13
|
export declare const mergeHeaders: (...headers: Array<Required<Config>["headers"] | undefined>) => Headers;
|
|
14
|
-
type ErrInterceptor<Err, Res, Req, Options> = (error: Err,
|
|
14
|
+
type ErrInterceptor<Err, Res, Req, Options> = (error: Err,
|
|
15
|
+
/** response may be undefined due to a network error where no response object is produced */
|
|
16
|
+
response: Res | undefined,
|
|
17
|
+
/** request may be undefined, because error may be from building the request object itself */
|
|
18
|
+
request: Req | undefined, options: Options) => Err | Promise<Err>;
|
|
15
19
|
type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;
|
|
16
20
|
type ResInterceptor<Res, Req, Options> = (response: Res, request: Req, options: Options) => Res | Promise<Res>;
|
|
17
21
|
declare class Interceptors<Interceptor> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.gen.d.ts","sourceRoot":"","sources":["../../../../src/generated/sonarr/client/utils.gen.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAQzE,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjF,eAAO,MAAM,qBAAqB,GAAI,CAAC,GAAG,OAAO,EAAE,0BAGhD,sBAA2B,mBACU,CAAC,WA6CxC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,aAAa,MAAM,GAAG,IAAI,KAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAgCxF,CAAC;AAqBF,eAAO,MAAM,aAAa,GAAU,0BAGjC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAC3C,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB,kBA8BF,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,UAAU,CAUpC,CAAC;AAEL,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAOnD,CAAC;AAUF,eAAO,MAAM,YAAY,GACvB,GAAG,SAAS,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,KACzD,OA2BF,CAAC;AAEF,KAAK,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,IAAI,CAC5C,KAAK,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"utils.gen.d.ts","sourceRoot":"","sources":["../../../../src/generated/sonarr/client/utils.gen.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
1
|
class p extends Error{code;statusCode;details;constructor(r,o,e,n){super(r);this.code=o;this.statusCode=e;this.details=n;this.name="TsarrError"}}class h extends p{constructor(r="Invalid or missing API key"){super(r,"API_KEY_ERROR",401);this.name="ApiKeyError"}}class c extends p{constructor(r,o){super(r,"CONNECTION_ERROR",void 0,o);this.name="ConnectionError"}}class K extends p{constructor(r,o){super(r,"VALIDATION_ERROR",void 0,o);this.name="ValidationError"}}class U extends p{constructor(r){super(`Resource not found: ${r}`,"NOT_FOUND",404);this.name="NotFoundError"}}var k=30000,B=3,$=1000,v=1e4,F=new Set([408,429,502,503,504]);function b(r){if(r instanceof DOMException&&r.name==="AbortError")return!1;if(r instanceof TypeError)return!0;return!1}function g(r,o,e){let n=o*2**r,s=n*0.2*Math.random();return Math.min(n+s,e)}function R(r={}){let o=r.timeout??k,e=r.retry?r.retry.maxRetries??B:0,n=r.retry?.initialDelayMs??$,s=r.retry?.maxDelayMs??v;return Object.assign(async(O,m)=>{let u,P=H(O,m);for(let d=0;d<=e;d++){let w=new AbortController,C=setTimeout(()=>w.abort(),o),f=m?.signal;if(f?.aborted)throw clearTimeout(C),f.reason??new DOMException("The operation was aborted.","AbortError");let N=()=>w.abort(f.reason);f?.addEventListener("abort",N,{once:!0});try{let t=await globalThis.fetch(new Request(P.clone(),{signal:w.signal}));if(clearTimeout(C),f?.removeEventListener("abort",N),F.has(t.status)&&d<e){u=new c(`Request failed with status ${t.status}`);let x=g(d,n,s);await new Promise((i)=>setTimeout(i,x));continue}return t}catch(t){if(clearTimeout(C),f?.removeEventListener("abort",N),f?.aborted)throw f.reason??new DOMException("The operation was aborted.","AbortError");if(t instanceof DOMException&&t.name==="AbortError"){if(u=new c(`Request timed out after ${o}ms`),d<e){let x=g(d,n,s);await new Promise((i)=>setTimeout(i,x));continue}throw u}if(b(t)&&d<e){u=t;let x=g(d,n,s);await new Promise((i)=>setTimeout(i,x));continue}throw t}}throw u},{preconnect:globalThis.fetch.preconnect?.bind(globalThis.fetch)})}function H(r,o){let{signal:e,...n}=o??{};if(r instanceof Request)return o?new Request(r.clone(),n):r.clone();return new Request(r,n)}var L=30000;function Z(r){if(!r.apiKey)throw new h;if(!r.baseUrl)throw new c("No base URL provided");let o={...r,baseUrl:r.baseUrl.replace(/\/$/,"")},e=o.timeout??L,n=R({timeout:e,retry:o.retry});return{config:o,getHeaders:()=>({"X-Api-Key":o.apiKey,"Content-Type":"application/json",...o.headers}),getBaseUrl:()=>o.baseUrl,getTimeout:()=>e,getFetch:()=>n}}function I(r){if(!r||r.trim()==="")throw new h;return r.trim()}function X(r){if(!r||r.trim()==="")throw new c("No base URL provided");let o;try{o=new URL(r)}catch{throw new c(`Failed to connect: Invalid URL: ${r}`)}if(o.protocol==="http:"&&!V(o.hostname))console.warn(`Warning: Using unencrypted HTTP for remote URL "${o.host}". Consider using HTTPS to protect your API key in transit.`);return r.trim().replace(/\/$/,"")}function V(r){return r==="localhost"||r==="127.0.0.1"||r==="::1"||r==="0.0.0.0"||r.endsWith(".local")||/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(r)}export{X as validateBaseUrl,I as validateApiKey,Z as createServarrClient,R as createResilientFetch,K as ValidationError,p as TsarrError,dr as SonarrClient,wr as Sonarr,er as SeerrClient,hr as Seerr,or as ReadarrClient,pr as Readarr,l as RadarrClient,ir as Radarr,M as QBittorrentClient,xr as QBittorrent,E as ProwlarrClient,ur as Prowlarr,U as NotFoundError,S as LidarrClient,sr as Lidarr,c as ConnectionError,q as BazarrClient,cr as Bazarr,h as ApiKeyError};
|
|
2
|
+
|
|
3
|
+
//# debugId=2DC55976B1F3DFC264756E2164756E21
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/errors.ts", "../src/core/fetch.ts", "../src/core/client.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"export class TsarrError extends Error {\n constructor(\n message: string,\n public code?: string,\n public statusCode?: number,\n public details?: unknown\n ) {\n super(message);\n this.name = 'TsarrError';\n }\n}\n\nexport class ApiKeyError extends TsarrError {\n constructor(message = 'Invalid or missing API key') {\n super(message, 'API_KEY_ERROR', 401);\n this.name = 'ApiKeyError';\n }\n}\n\nexport class ConnectionError extends TsarrError {\n constructor(message: string, details?: unknown) {\n super(message, 'CONNECTION_ERROR', undefined, details);\n this.name = 'ConnectionError';\n }\n}\n\nexport class ValidationError extends TsarrError {\n constructor(message: string, details?: unknown) {\n super(message, 'VALIDATION_ERROR', undefined, details);\n this.name = 'ValidationError';\n }\n}\n\nexport class NotFoundError extends TsarrError {\n constructor(resource: string) {\n super(`Resource not found: ${resource}`, 'NOT_FOUND', 404);\n this.name = 'NotFoundError';\n }\n}\n",
|
|
6
|
+
"import { ConnectionError } from './errors';\n\nexport interface RetryOptions {\n /** Maximum number of retry attempts for transient failures (default: 3) */\n maxRetries?: number;\n /** Initial delay in ms before the first retry (default: 1000) */\n initialDelayMs?: number;\n /** Maximum delay in ms between retries (default: 10000) */\n maxDelayMs?: number;\n}\n\nexport interface ResilientFetchOptions {\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Retry configuration for transient failures. Omit to disable retries. */\n retry?: RetryOptions;\n}\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_INITIAL_DELAY = 1_000;\nconst DEFAULT_MAX_DELAY = 10_000;\n\nconst RETRYABLE_STATUS_CODES = new Set([408, 429, 502, 503, 504]);\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof DOMException && error.name === 'AbortError') {\n return false;\n }\n if (error instanceof TypeError) {\n // Network errors from fetch (e.g. DNS failure, connection refused)\n return true;\n }\n return false;\n}\n\nfunction getRetryDelay(attempt: number, initialDelayMs: number, maxDelayMs: number): number {\n const delay = initialDelayMs * 2 ** attempt;\n const jitter = delay * 0.2 * Math.random();\n return Math.min(delay + jitter, maxDelayMs);\n}\n\n/**\n * Creates a fetch function with timeout and retry support.\n *\n * - Timeout uses AbortController to cancel requests that exceed the limit.\n * - Retry uses exponential backoff with jitter for transient failures\n * (network errors and 408/429/502/503/504 status codes).\n */\nexport function createResilientFetch(options: ResilientFetchOptions = {}): typeof fetch {\n const timeout = options.timeout ?? DEFAULT_TIMEOUT;\n const maxRetries = options.retry ? (options.retry.maxRetries ?? DEFAULT_MAX_RETRIES) : 0;\n const initialDelayMs = options.retry?.initialDelayMs ?? DEFAULT_INITIAL_DELAY;\n const maxDelayMs = options.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY;\n\n const resilientFetch = async (\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> => {\n let lastError: unknown;\n const template = createRequestTemplate(input, init);\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n // Merge abort signals: respect caller's signal and our timeout\n const callerSignal = init?.signal;\n if (callerSignal?.aborted) {\n clearTimeout(timeoutId);\n throw callerSignal.reason ?? new DOMException('The operation was aborted.', 'AbortError');\n }\n\n const onCallerAbort = () => controller.abort(callerSignal!.reason);\n callerSignal?.addEventListener('abort', onCallerAbort, { once: true });\n\n try {\n const response = await globalThis.fetch(\n new Request(template.clone(), { signal: controller.signal })\n );\n\n clearTimeout(timeoutId);\n callerSignal?.removeEventListener('abort', onCallerAbort);\n\n if (RETRYABLE_STATUS_CODES.has(response.status) && attempt < maxRetries) {\n lastError = new ConnectionError(`Request failed with status ${response.status}`);\n const delay = getRetryDelay(attempt, initialDelayMs, maxDelayMs);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n callerSignal?.removeEventListener('abort', onCallerAbort);\n\n // If the caller aborted, don't retry\n if (callerSignal?.aborted) {\n throw callerSignal.reason ?? new DOMException('The operation was aborted.', 'AbortError');\n }\n\n // Timeout: wrap as ConnectionError\n if (error instanceof DOMException && error.name === 'AbortError') {\n lastError = new ConnectionError(`Request timed out after ${timeout}ms`);\n if (attempt < maxRetries) {\n const delay = getRetryDelay(attempt, initialDelayMs, maxDelayMs);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n throw lastError;\n }\n\n if (isRetryable(error) && attempt < maxRetries) {\n lastError = error;\n const delay = getRetryDelay(attempt, initialDelayMs, maxDelayMs);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n throw error;\n }\n }\n\n throw lastError;\n };\n\n return Object.assign(resilientFetch, {\n preconnect: globalThis.fetch.preconnect?.bind(globalThis.fetch),\n }) as typeof fetch;\n}\n\nfunction createRequestTemplate(input: RequestInfo | URL, init?: RequestInit): Request {\n const { signal: _signal, ...requestInit } = init ?? {};\n\n if (input instanceof Request) {\n return init ? new Request(input.clone(), requestInit) : input.clone();\n }\n\n return new Request(input, requestInit);\n}\n",
|
|
7
|
+
"import { ApiKeyError, ConnectionError } from './errors';\nimport { createResilientFetch } from './fetch';\nimport type { ServarrClientConfig } from './types';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function createServarrClient(config: ServarrClientConfig) {\n if (!config.apiKey) {\n throw new ApiKeyError();\n }\n\n if (!config.baseUrl) {\n throw new ConnectionError('No base URL provided');\n }\n\n const validatedConfig = {\n ...config,\n baseUrl: config.baseUrl.replace(/\\/$/, ''),\n };\n\n const timeoutMs = validatedConfig.timeout ?? DEFAULT_TIMEOUT_MS;\n\n const resilientFetch = createResilientFetch({\n timeout: timeoutMs,\n retry: validatedConfig.retry,\n });\n\n return {\n config: validatedConfig,\n getHeaders: () => ({\n 'X-Api-Key': validatedConfig.apiKey,\n 'Content-Type': 'application/json',\n ...validatedConfig.headers,\n }),\n getBaseUrl: () => validatedConfig.baseUrl,\n getTimeout: () => timeoutMs,\n getFetch: () => resilientFetch,\n };\n}\n\nexport function validateApiKey(apiKey: string | undefined): string {\n if (!apiKey || apiKey.trim() === '') {\n throw new ApiKeyError();\n }\n return apiKey.trim();\n}\n\nexport function validateBaseUrl(baseUrl: string | undefined): string {\n if (!baseUrl || baseUrl.trim() === '') {\n throw new ConnectionError('No base URL provided');\n }\n\n let parsed: URL;\n try {\n parsed = new URL(baseUrl);\n } catch {\n throw new ConnectionError(`Failed to connect: Invalid URL: ${baseUrl}`);\n }\n\n if (parsed.protocol === 'http:' && !isLocalhost(parsed.hostname)) {\n console.warn(\n `Warning: Using unencrypted HTTP for remote URL \"${parsed.host}\". Consider using HTTPS to protect your API key in transit.`\n );\n }\n\n return baseUrl.trim().replace(/\\/$/, '');\n}\n\nfunction isLocalhost(hostname: string): boolean {\n return (\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname === '::1' ||\n hostname === '0.0.0.0' ||\n hostname.endsWith('.local') ||\n /^(10\\.|172\\.(1[6-9]|2\\d|3[01])\\.|192\\.168\\.)/.test(hostname)\n );\n}\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "2DC55976B1F3DFC264756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsarr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"author": "Robbe Verhelst",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,16 +12,17 @@
|
|
|
12
12
|
"main": "dist/index.js",
|
|
13
13
|
"module": "dist/index.js",
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@biomejs/biome": "2.4.
|
|
16
|
-
"@hey-api/openapi-ts": "^0.
|
|
15
|
+
"@biomejs/biome": "2.4.15",
|
|
16
|
+
"@hey-api/openapi-ts": "^0.97.1",
|
|
17
17
|
"@semantic-release/changelog": "^6.0.3",
|
|
18
18
|
"@semantic-release/git": "^10.0.1",
|
|
19
|
-
"@semantic-release/github": "^12.0.
|
|
19
|
+
"@semantic-release/github": "^12.0.8",
|
|
20
20
|
"@semantic-release/npm": "^13.1.5",
|
|
21
|
-
"@types/bun": "^1.3.
|
|
21
|
+
"@types/bun": "^1.3.13",
|
|
22
22
|
"semantic-release": "^25.0.3",
|
|
23
|
+
"type-coverage": "^2.29.7",
|
|
23
24
|
"typedoc": "^0.28.19",
|
|
24
|
-
"typescript": "^6.0.
|
|
25
|
+
"typescript": "^6.0.3"
|
|
25
26
|
},
|
|
26
27
|
"exports": {
|
|
27
28
|
".": {
|
|
@@ -114,12 +115,13 @@
|
|
|
114
115
|
"license": "MIT",
|
|
115
116
|
"publishConfig": {
|
|
116
117
|
"access": "public",
|
|
117
|
-
"registry": "https://registry.npmjs.org/"
|
|
118
|
+
"registry": "https://registry.npmjs.org/",
|
|
119
|
+
"provenance": false
|
|
118
120
|
},
|
|
119
121
|
"scripts": {
|
|
120
122
|
"build": "bun run generate && bun run generate:types && bun run build:js && bun run build:cli && bun run build:types",
|
|
121
|
-
"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",
|
|
122
|
-
"build:cli": "bun build src/cli/index.ts --outdir dist/cli --target node --format esm && chmod +x dist/cli/index.js",
|
|
123
|
+
"build:js": "bun build src/index.ts --outdir dist --target node --minify --splitting --sourcemap=linked && bun build src/clients/radarr.ts --outdir dist/clients --target node --format esm --sourcemap=linked && bun build src/clients/sonarr.ts --outdir dist/clients --target node --format esm --sourcemap=linked && bun build src/clients/lidarr.ts --outdir dist/clients --target node --format esm --sourcemap=linked && bun build src/clients/readarr.ts --outdir dist/clients --target node --format esm --sourcemap=linked && bun build src/clients/prowlarr.ts --outdir dist/clients --target node --format esm --sourcemap=linked && bun build src/clients/bazarr.ts --outdir dist/clients --target node --format esm --sourcemap=linked && bun build src/clients/qbittorrent.ts --outdir dist/clients --target node --format esm --sourcemap=linked && bun build src/clients/seerr.ts --outdir dist/clients --target node --format esm --sourcemap=linked",
|
|
124
|
+
"build:cli": "bun build src/cli/index.ts --outdir dist/cli --target node --format esm --sourcemap=linked && chmod +x dist/cli/index.js",
|
|
123
125
|
"build:types": "tsc --project tsconfig.build.json",
|
|
124
126
|
"prepublishOnly": "bun run build",
|
|
125
127
|
"test": "bun test",
|
|
@@ -129,6 +131,7 @@
|
|
|
129
131
|
"lint:fix": "biome check . --write",
|
|
130
132
|
"format": "biome format . --write",
|
|
131
133
|
"typecheck": "tsc --noEmit",
|
|
134
|
+
"typecheck:coverage": "type-coverage",
|
|
132
135
|
"generate": "bun run scripts/generate.ts",
|
|
133
136
|
"refresh:specs": "bun run scripts/refresh-specs.ts",
|
|
134
137
|
"generate:types": "bun run scripts/generate-type-exports.ts",
|
|
@@ -142,6 +145,12 @@
|
|
|
142
145
|
"sideEffects": false,
|
|
143
146
|
"type": "module",
|
|
144
147
|
"types": "dist/index.d.ts",
|
|
148
|
+
"typeCoverage": {
|
|
149
|
+
"atLeast": 98,
|
|
150
|
+
"strict": true,
|
|
151
|
+
"ignoreCatch": true,
|
|
152
|
+
"cache": true
|
|
153
|
+
},
|
|
145
154
|
"dependencies": {
|
|
146
155
|
"citty": "^0.2.2",
|
|
147
156
|
"consola": "^3.4.2"
|
package/dist/tsarr-2.10.0.tgz
DELETED
|
Binary file
|