diff --git a/lib/rclone/api.ts b/lib/rclone/api.ts index f1accdf..e13b967 100644 --- a/lib/rclone/api.ts +++ b/lib/rclone/api.ts @@ -8,7 +8,7 @@ import type { JobItem } from '../../types/jobs' import type { FlagValue } from '../../types/rclone' import { getFsInfo } from '../format' import { restartActiveRclone, runRcloneCli } from './cli' -import rclone from './client' +import rclone, { rcloneAsync } from './client' import { parseRcloneOptions } from './common' const RE_BACKSLASH = /\\/g @@ -19,7 +19,6 @@ const RE_WINDOWS_DRIVE_LETTER = /^[a-zA-Z]:$/ export async function startDryRun(operation: () => Promise): Promise { await rclone('/options/set', { - // @ts-ignore body: { main: { DryRun: true }, }, @@ -34,7 +33,6 @@ export async function startDryRun(operation: () => Promise): Promise { return result } finally { await rclone('/options/set', { - // @ts-ignore body: { main: { DryRun: false }, }, @@ -186,7 +184,7 @@ export async function startCopy({ const dstOptions = options.remotes && dstRemoteName && dstRemoteName in options.remotes - ? (JSON.parse(options.remotes[dstRemoteName] as unknown as string) as any) + ? options.remotes[dstRemoteName] : undefined for (const source of sources) { @@ -213,7 +211,7 @@ export async function startCopy({ const srcOptions = options.remotes && srcRemoteName && srcRemoteName in options.remotes - ? (JSON.parse(options.remotes[srcRemoteName] as unknown as string) as any) + ? options.remotes[srcRemoteName] : undefined if (srcType === 'folder') { @@ -318,7 +316,7 @@ export async function startMove({ const dstOptions = options.remotes && dstRemoteName && dstRemoteName in options.remotes - ? (JSON.parse(options.remotes[dstRemoteName] as unknown as string) as any) + ? options.remotes[dstRemoteName] : undefined for (const source of sources) { @@ -340,7 +338,7 @@ export async function startMove({ const srcOptions = options.remotes && srcRemoteName && srcRemoteName in options.remotes - ? (JSON.parse(options.remotes[srcRemoteName] as unknown as string) as any) + ? options.remotes[srcRemoteName] : undefined if (srcType === 'folder') { @@ -640,7 +638,7 @@ export async function startMount({ const srcOptions = options.remotes && srcRemoteName && srcRemoteName in options.remotes - ? (JSON.parse(options.remotes[srcRemoteName] as unknown as string) as any) + ? options.remotes[srcRemoteName] : undefined if (destination === '*' && currentPlatform === 'windows') { @@ -662,7 +660,7 @@ export async function startMount({ retries: 3, } ) - return response?.mountPoint as string | undefined + return response?.mountPoint } const { @@ -837,17 +835,17 @@ export async function startBisync({ const srcOptions = options.remotes && srcRemoteName && srcRemoteName in options.remotes - ? (JSON.parse(options.remotes[srcRemoteName] as unknown as string) as any) + ? options.remotes[srcRemoteName] : undefined const dstOptions = options.remotes && dstRemoteName && dstRemoteName in options.remotes - ? (JSON.parse(options.remotes[dstRemoteName] as unknown as string) as any) + ? options.remotes[dstRemoteName] : undefined const r = await pRetry( async () => - await rclone('/sync/bisync', { + await rcloneAsync('/sync/bisync', { params: { query: { path1: serializeOptions(srcFullDirPath, { @@ -857,7 +855,6 @@ export async function startBisync({ path2: serializeOptions(dstFullDirPath, { remote: dstOptions, }), - _async: true, ...(options.outer && Object.keys(options.outer).length > 0 ? Object.fromEntries( Object.entries(options.outer).map(([key, value]) => [ @@ -886,7 +883,7 @@ export async function startBisync({ await rclone('/job/status', { params: { query: { - jobid: r.jobid!, + jobid: r.jobid, }, }, }), @@ -940,17 +937,17 @@ export async function startSync({ const srcOptions = options.remotes && srcRemoteName && srcRemoteName in options.remotes - ? (JSON.parse(options.remotes[srcRemoteName] as unknown as string) as any) + ? options.remotes[srcRemoteName] : undefined const dstOptions = options.remotes && dstRemoteName && dstRemoteName in options.remotes - ? (JSON.parse(options.remotes[dstRemoteName] as unknown as string) as any) + ? options.remotes[dstRemoteName] : undefined const r = await pRetry( async () => - await rclone('/sync/sync', { + await rcloneAsync('/sync/sync', { params: { query: { srcFs: serializeOptions(srcFullDirPath, { @@ -961,7 +958,6 @@ export async function startSync({ remote: dstOptions, }), createEmptySrcDirs: true, - _async: true, }, }, }), @@ -982,7 +978,7 @@ export async function startSync({ await rclone('/job/status', { params: { query: { - jobid: r.jobid!, + jobid: r.jobid, }, }, }), @@ -1058,7 +1054,7 @@ export async function startDelete({ const srcOptions = options.remotes && srcRemoteName && srcRemoteName in options.remotes - ? (JSON.parse(options.remotes[srcRemoteName] as unknown as string) as any) + ? options.remotes[srcRemoteName] : undefined if (srcType === 'folder') { @@ -1136,7 +1132,7 @@ export async function startPurge({ const srcOptions = options.remotes && srcRemoteName && srcRemoteName in options.remotes - ? (JSON.parse(options.remotes[srcRemoteName] as unknown as string) as any) + ? options.remotes[srcRemoteName] : undefined const jobParams: Parameters[0][number] = { diff --git a/lib/rclone/client.ts b/lib/rclone/client.ts index fb428a3..be9ad51 100644 --- a/lib/rclone/client.ts +++ b/lib/rclone/client.ts @@ -1,6 +1,7 @@ import { fetch as tauriFetch } from '@tauri-apps/plugin-http' import pRetry from 'p-retry' import createRCDClient, { + type AsyncJobResponse, type OpenApiMethodResponse, type OpenApiClient, type OpenApiClientPathsWithMethod, @@ -110,3 +111,58 @@ export default async function rclone< return result.data as OpenApiMethodResponse } + +export async function rcloneAsync< + Path extends OpenApiClientPathsWithMethod, + Init extends OpenApiMaybeOptionalInit = OpenApiMaybeOptionalInit< + Paths[Path], + 'post' + >, +>( + path: Path, + ...init: InitParam +): Promise { + console.log('[rclone] ASYNC REQUEST', path, { + params: init[0]?.params, + body: init[0]?.body, + }) + + const client = await pRetry(() => getClient(), { + 'maxTimeout': 500, + }) + + if (!client) { + console.error('[rclone] ERROR: Failed to get client after retries', path) + throw new Error('Failed to get client after retries') + } + + const result = await client.ASYNC(path, ...(init as [any])) + + if (result?.error) { + console.error('[rclone] ERROR', path, { error: result.error }) + const message = + typeof result.error === 'string' ? result.error : JSON.stringify(result.error) + + throw new Error(message) + } + + const data = result.data as { error?: unknown } | undefined + if (data?.error) { + console.error('[rclone] DATA ERROR', path, { error: data.error }) + const message = typeof data.error === 'string' ? data.error : JSON.stringify(data.error) + + throw new Error(message) + } + + if (!result.response.ok) { + console.error('[rclone] HTTP ERROR', path, { + status: result.response.status, + statusText: result.response.statusText, + }) + throw new Error(`${result.response.status} ${result.response.statusText}`) + } + + console.log('[rclone] ASYNC RESPONSE', path, { hasData: !!result.data }) + + return result.data as AsyncJobResponse +}