recappi 0.1.61 → 0.1.63
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/dist/index.js +60 -10
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -18588,7 +18588,12 @@ function isNodeErrorCode(error51, code) {
|
|
|
18588
18588
|
}
|
|
18589
18589
|
async function readDurationMs(filePath, contentType) {
|
|
18590
18590
|
if (contentType === "audio/wav") {
|
|
18591
|
-
|
|
18591
|
+
let handle;
|
|
18592
|
+
try {
|
|
18593
|
+
handle = await fs2.open(filePath, "r");
|
|
18594
|
+
} catch (error51) {
|
|
18595
|
+
throwReadablePathError(filePath, error51);
|
|
18596
|
+
}
|
|
18592
18597
|
try {
|
|
18593
18598
|
const buffer = Buffer.alloc(4096);
|
|
18594
18599
|
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
@@ -18603,7 +18608,10 @@ async function readDurationMs(filePath, contentType) {
|
|
|
18603
18608
|
if (typeof metadata.format.duration === "number" && Number.isFinite(metadata.format.duration)) {
|
|
18604
18609
|
return Math.max(1, Math.round(metadata.format.duration * 1e3));
|
|
18605
18610
|
}
|
|
18606
|
-
} catch {
|
|
18611
|
+
} catch (error51) {
|
|
18612
|
+
if (isPermissionDenied(error51)) {
|
|
18613
|
+
throwPermissionDenied(filePath);
|
|
18614
|
+
}
|
|
18607
18615
|
throw cliError(
|
|
18608
18616
|
"input.duration_unavailable",
|
|
18609
18617
|
`Could not read duration for non-WAV file: ${filePath}`,
|
|
@@ -18620,6 +18628,28 @@ async function readDurationMs(filePath, contentType) {
|
|
|
18620
18628
|
}
|
|
18621
18629
|
);
|
|
18622
18630
|
}
|
|
18631
|
+
function throwReadablePathError(filePath, error51) {
|
|
18632
|
+
if (isPermissionDenied(error51)) {
|
|
18633
|
+
throwPermissionDenied(filePath);
|
|
18634
|
+
}
|
|
18635
|
+
throw error51;
|
|
18636
|
+
}
|
|
18637
|
+
function throwPermissionDenied(filePath) {
|
|
18638
|
+
throw cliError("input.permission_denied", `Permission denied reading path: ${filePath}`, {
|
|
18639
|
+
hint: "Grant this terminal/agent access to the file, or copy the audio to a readable location."
|
|
18640
|
+
});
|
|
18641
|
+
}
|
|
18642
|
+
function isPermissionDenied(error51) {
|
|
18643
|
+
if (isNodeErrorCode(error51, "EACCES") || isNodeErrorCode(error51, "EPERM")) return true;
|
|
18644
|
+
if (typeof error51 === "object" && error51 !== null && "cause" in error51) {
|
|
18645
|
+
const cause = error51.cause;
|
|
18646
|
+
if (cause && cause !== error51 && isPermissionDenied(cause)) return true;
|
|
18647
|
+
}
|
|
18648
|
+
if (error51 instanceof Error) {
|
|
18649
|
+
return /(?:EACCES|EPERM|permission denied|operation not permitted)/i.test(error51.message);
|
|
18650
|
+
}
|
|
18651
|
+
return false;
|
|
18652
|
+
}
|
|
18623
18653
|
|
|
18624
18654
|
// src/store.ts
|
|
18625
18655
|
import { mkdirSync } from "fs";
|
|
@@ -19478,14 +19508,27 @@ var RecappiApiClient = class {
|
|
|
19478
19508
|
}
|
|
19479
19509
|
async request(method, pathname, body, opts = {}) {
|
|
19480
19510
|
const token = requireToken(this.auth);
|
|
19481
|
-
|
|
19482
|
-
|
|
19483
|
-
|
|
19484
|
-
|
|
19485
|
-
|
|
19486
|
-
|
|
19487
|
-
|
|
19488
|
-
|
|
19511
|
+
let response;
|
|
19512
|
+
try {
|
|
19513
|
+
response = await this.fetchImpl(new URL(pathname, this.auth.origin), {
|
|
19514
|
+
method,
|
|
19515
|
+
headers: {
|
|
19516
|
+
authorization: `Bearer ${token}`,
|
|
19517
|
+
...opts.headers
|
|
19518
|
+
},
|
|
19519
|
+
...body ? { body } : {}
|
|
19520
|
+
});
|
|
19521
|
+
} catch (error51) {
|
|
19522
|
+
if (error51 instanceof RecappiCliError) throw error51;
|
|
19523
|
+
throw cliError(
|
|
19524
|
+
"cloud.http_error",
|
|
19525
|
+
`Recappi Cloud request failed: ${transportErrorMessage(error51)}`,
|
|
19526
|
+
{
|
|
19527
|
+
retryable: true,
|
|
19528
|
+
hint: `Check your network connection and Recappi Cloud origin (${this.auth.origin}), then retry.`
|
|
19529
|
+
}
|
|
19530
|
+
);
|
|
19531
|
+
}
|
|
19489
19532
|
if (!response.ok && !(opts.allowAuthFailure && (response.status === 401 || response.status === 403))) {
|
|
19490
19533
|
const message = await responseMessage(response);
|
|
19491
19534
|
throw new RecappiCliError(describeHttpError(response.status, message));
|
|
@@ -19493,6 +19536,10 @@ var RecappiApiClient = class {
|
|
|
19493
19536
|
return response;
|
|
19494
19537
|
}
|
|
19495
19538
|
};
|
|
19539
|
+
function transportErrorMessage(error51) {
|
|
19540
|
+
if (error51 instanceof Error && error51.message) return error51.message;
|
|
19541
|
+
return String(error51 || "network request failed");
|
|
19542
|
+
}
|
|
19496
19543
|
async function parseJson(response) {
|
|
19497
19544
|
try {
|
|
19498
19545
|
return await response.json();
|
|
@@ -20236,8 +20283,11 @@ function renderFailure(command, error51, opts, data) {
|
|
|
20236
20283
|
for (const item of data.failures) {
|
|
20237
20284
|
const label = humanFileLabel(item.filePath) ?? item.filePath;
|
|
20238
20285
|
opts.stderr(` ${label}: ${item.error.message} (${item.error.code})
|
|
20286
|
+
`);
|
|
20287
|
+
if (item.error.hint) opts.stderr(` ${item.error.hint}
|
|
20239
20288
|
`);
|
|
20240
20289
|
}
|
|
20290
|
+
return;
|
|
20241
20291
|
}
|
|
20242
20292
|
if (error51.hint) opts.stderr(`${error51.hint}
|
|
20243
20293
|
`);
|