recappi 0.1.61 → 0.1.62

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 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
- const handle = await fs2.open(filePath, "r");
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";
@@ -20236,8 +20266,11 @@ function renderFailure(command, error51, opts, data) {
20236
20266
  for (const item of data.failures) {
20237
20267
  const label = humanFileLabel(item.filePath) ?? item.filePath;
20238
20268
  opts.stderr(` ${label}: ${item.error.message} (${item.error.code})
20269
+ `);
20270
+ if (item.error.hint) opts.stderr(` ${item.error.hint}
20239
20271
  `);
20240
20272
  }
20273
+ return;
20241
20274
  }
20242
20275
  if (error51.hint) opts.stderr(`${error51.hint}
20243
20276
  `);