Explorar o código

Improve ripgrep error handling with structured error types

🤖 Generated with [OpenCode](https://opencode.ai)

Co-Authored-By: OpenCode <[email protected]>
Dax Raad hai 8 meses
pai
achega
34fa8cadd6
Modificáronse 1 ficheiros con 35 adicións e 4 borrados
  1. 35 4
      packages/opencode/src/ripgrep/index.ts

+ 35 - 4
packages/opencode/src/ripgrep/index.ts

@@ -2,6 +2,8 @@ import { App } from "../app/app"
 import path from "path"
 import { Global } from "../global"
 import fs from "fs/promises"
+import { z } from "zod"
+import { NamedError } from "../util/error"
 
 export namespace Ripgrep {
   const PLATFORM = {
@@ -10,6 +12,29 @@ export namespace Ripgrep {
     win32: { platform: "pc-windows-msvc", extension: "zip" },
   } as const
 
+  export const ExtractionFailedError = NamedError.create(
+    "RipgrepExtractionFailedError",
+    z.object({
+      filepath: z.string(),
+      stderr: z.string(),
+    }),
+  )
+
+  export const UnsupportedPlatformError = NamedError.create(
+    "RipgrepUnsupportedPlatformError",
+    z.object({
+      platform: z.string(),
+    }),
+  )
+
+  export const DownloadFailedError = NamedError.create(
+    "RipgrepDownloadFailedError",
+    z.object({
+      url: z.string(),
+      status: z.number(),
+    }),
+  )
+
   const state = App.state("ripgrep", async () => {
     const filepath = path.join(
       Global.Path.bin,
@@ -22,7 +47,8 @@ export namespace Ripgrep {
       const arch = archMap[process.arch as keyof typeof archMap] ?? process.arch
 
       const config = PLATFORM[process.platform as keyof typeof PLATFORM]
-      if (!config) throw new Error(`Unsupported platform: ${process.platform}`)
+      if (!config)
+        throw new UnsupportedPlatformError({ platform: process.platform })
 
       const version = "14.1.1"
       const filename = `ripgrep-${version}-${arch}-${config.platform}.${config.extension}`
@@ -30,7 +56,7 @@ export namespace Ripgrep {
 
       const response = await fetch(url)
       if (!response.ok)
-        throw new Error(`Failed to download ripgrep: ${response.statusText}`)
+        throw new DownloadFailedError({ url, status: response.status })
 
       const buffer = await response.arrayBuffer()
       const archivePath = path.join(Global.Path.bin, filename)
@@ -52,6 +78,8 @@ export namespace Ripgrep {
           },
         )
         await proc.exited
+        if (proc.exitCode !== 0)
+          throw new ExtractionFailedError({ filepath, stderr: proc.stderr })
       }
       if (config.extension === "zip") {
         const proc = Bun.spawn(
@@ -63,10 +91,13 @@ export namespace Ripgrep {
           },
         )
         await proc.exited
+        if (proc.exitCode !== 0)
+          throw new ExtractionFailedError({
+            filepath: archivePath,
+            stderr: proc.stderr,
+          })
       }
-
       await fs.unlink(archivePath)
-
       if (process.platform !== "win32") await fs.chmod(filepath, 0o755)
     }