diff --git a/packages/opencode/src/cli/cmd/import.ts b/packages/opencode/src/cli/cmd/import.ts index 9eb151b633e8..1b7350f74478 100644 --- a/packages/opencode/src/cli/cmd/import.ts +++ b/packages/opencode/src/cli/cmd/import.ts @@ -38,6 +38,17 @@ export function shouldAttachShareAuthHeaders(shareUrl: string, accountBaseUrl: s } } +export function formatImportFileError(file: string, error: FSUtil.Error) { + if (error._tag === "PlatformError") { + if (error.reason._tag === "NotFound") return `File not found: ${file}` + if (error.reason._tag === "PermissionDenied") return `Failed to read file: Permission denied` + return `Failed to read file: ${error.message}` + } + + const detail = error.cause instanceof Error ? error.cause.message : error.message + return `Invalid JSON in ${file}: ${detail}` +} + /** * Transform ShareNext API response (flat array) into the nested structure for local file storage. * @@ -154,14 +165,9 @@ const runImport = Effect.fn("Cli.import.body")(function* (file: string, ctx: Ins exportData = transformed } else { - exportData = (yield* fs.readJson(file).pipe(Effect.orElseSucceed(() => undefined))) as - | NonNullable - | undefined - if (!exportData) { - process.stdout.write(`File not found: ${file}`) - process.stdout.write(EOL) - return - } + exportData = (yield* fs + .readJson(file) + .pipe(Effect.mapError((error) => new CliError({ message: formatImportFileError(file, error) })))) as ExportData } if (!exportData) { diff --git a/packages/opencode/test/cli/import.test.ts b/packages/opencode/test/cli/import.test.ts index d7c0241e6b0b..59824c3efcb9 100644 --- a/packages/opencode/test/cli/import.test.ts +++ b/packages/opencode/test/cli/import.test.ts @@ -1,10 +1,46 @@ import { test, expect } from "bun:test" import { + formatImportFileError, parseShareUrl, shouldAttachShareAuthHeaders, transformShareData, type ShareData, } from "../../src/cli/cmd/import" +import { FSUtil } from "@opencode-ai/core/fs-util" +import { PlatformError } from "effect" + +test("formats import file errors", () => { + expect( + formatImportFileError( + "test.json", + new PlatformError.PlatformError( + new PlatformError.SystemError({ + _tag: "NotFound", + module: "FileSystem", + method: "readFileString", + }), + ), + ), + ).toBe("File not found: test.json") + expect( + formatImportFileError( + "test.json", + new PlatformError.PlatformError( + new PlatformError.SystemError({ + _tag: "PermissionDenied", + module: "FileSystem", + method: "readFileString", + }), + ), + ), + ).toBe("Failed to read file: Permission denied") + expect( + formatImportFileError( + "test.json", + new FSUtil.FileSystemError({ method: "readJson", cause: new SyntaxError("Unexpected token") }), + ), + ).toBe("Invalid JSON in test.json: Unexpected token") +}) // parseShareUrl tests test("parses valid share URLs", () => {