diff --git a/cmd/dbc/info.go b/cmd/dbc/info.go index 9b0350e9..a330997c 100644 --- a/cmd/dbc/info.go +++ b/cmd/dbc/info.go @@ -20,6 +20,7 @@ import ( "strings" tea "charm.land/bubbletea/v2" + "charm.land/lipgloss/v2" "github.com/columnar-tech/dbc" "github.com/columnar-tech/dbc/internal/jsonschema" ) @@ -85,6 +86,9 @@ func formatDriverInfo(drv dbc.Driver) string { b.WriteString(bold.Render("Title: ") + drv.Title + "\n") b.WriteString(bold.Render("License: ") + drv.License + "\n") b.WriteString(bold.Render("Description: ") + drv.Desc + "\n") + if drv.DocsURL != "" { + b.WriteString(bold.Render("Documentation: ") + lipgloss.NewStyle().Hyperlink(drv.DocsURL).Render(drv.DocsURL) + "\n") + } b.WriteString(bold.Render("Available Packages:") + "\n") for _, pkg := range info.Packages { b.WriteString(" - " + descStyle.Render(pkg.Platform) + "\n") @@ -105,6 +109,7 @@ func driverInfoJSON(drv dbc.Driver) string { Title: drv.Title, License: drv.License, Description: drv.Desc, + DocsURL: drv.DocsURL, } for _, pkg := range info.Packages { driverInfo.Packages = append(driverInfo.Packages, pkg.Platform) diff --git a/cmd/dbc/info_test.go b/cmd/dbc/info_test.go index b04e65f5..bd855c02 100644 --- a/cmd/dbc/info_test.go +++ b/cmd/dbc/info_test.go @@ -33,6 +33,21 @@ func (suite *SubcommandTestSuite) TestInfo() { "Available Packages:\n"+ " - linux_amd64\n - macos_amd64\n"+ " - macos_arm64\n - windows_amd64", out) + suite.NotContains(out, "Documentation:") +} + +func (suite *SubcommandTestSuite) TestInfo_DocsURL() { + m := InfoCmd{Driver: "test-driver-docs-url"}. + GetModelCustom(testBaseModel()) + out := suite.runCmd(m) + + suite.validateOutput("\r ", "Driver: test-driver-docs-url\n"+ + "Version: 1.0.0\nTitle: Test Driver With Docs URL Set\n"+ + "License: Apache-2.0\nDescription: This is manifest-only with its docs_url key set\n"+ + "Documentation: http://example.com\n"+ + "Available Packages:\n"+ + " - linux_amd64\n - macos_amd64\n"+ + " - macos_arm64\n - windows_amd64", out) } func (suite *SubcommandTestSuite) TestInfo_DriverNotFound() { @@ -113,6 +128,21 @@ func (suite *SubcommandTestSuite) TestInfo_JSON() { suite.Equal("1.1.0", info.Version) suite.NotEmpty(info.Title) suite.NotEmpty(info.Packages) + suite.Empty(info.DocsURL) +} + +func (suite *SubcommandTestSuite) TestInfo_JSON_DocsURL() { + m := InfoCmd{Driver: "test-driver-docs-url", Json: true}. + GetModelCustom(baseModel{getDriverRegistry: getTestDriverRegistry, downloadPkg: downloadTestPkg}) + out := suite.runCmd(m) + + var env jsonschema.Envelope + suite.Require().NoError(json.Unmarshal([]byte(out), &env), "output must be valid JSON: %s", out) + + var info jsonschema.DriverInfo + suite.Require().NoError(json.Unmarshal(env.Payload, &info)) + suite.Equal("test-driver-docs-url", info.Driver) + suite.Equal("http://example.com", info.DocsURL) } func (suite *SubcommandTestSuite) TestInfo_JSON_DriverNotFound() { diff --git a/internal/jsonschema/schema.go b/internal/jsonschema/schema.go index 22e1737d..193caac3 100644 --- a/internal/jsonschema/schema.go +++ b/internal/jsonschema/schema.go @@ -153,6 +153,8 @@ type DriverInfo struct { License string `json:"license"` // Description is a detailed description of the driver. Description string `json:"description"` + // DocsURL is the URL of the driver's documentation, or empty if none. + DocsURL string `json:"docs_url"` // Packages lists the supported platform tuples. Packages []string `json:"packages"` } diff --git a/internal/jsonschema/schema_test.go b/internal/jsonschema/schema_test.go index 7c2d3087..f9b41f5e 100644 --- a/internal/jsonschema/schema_test.go +++ b/internal/jsonschema/schema_test.go @@ -289,6 +289,7 @@ func TestDriverInfo(t *testing.T) { Title: "Snowflake Driver", License: "Apache-2.0", Description: "Connects to Snowflake via ADBC", + DocsURL: "https://docs.example.com/snowflake", Packages: []string{"linux-amd64", "darwin-arm64"}, } b, _ := json.Marshal(v) @@ -297,7 +298,7 @@ func TestDriverInfo(t *testing.T) { t.Fatalf("unmarshal: %v", err) } if got.Driver != v.Driver || got.Version != v.Version || got.Title != v.Title || - got.License != v.License || got.Description != v.Description { + got.License != v.License || got.Description != v.Description || got.DocsURL != v.DocsURL { t.Errorf("field mismatch: %+v", got) } if len(got.Packages) != 2 { @@ -310,7 +311,7 @@ func TestDriverInfo_JSONFieldNames(t *testing.T) { b, _ := json.Marshal(v) var m map[string]interface{} _ = json.Unmarshal(b, &m) - for _, key := range []string{"driver", "version", "title", "license", "description", "packages"} { + for _, key := range []string{"driver", "version", "title", "license", "description", "docs_url", "packages"} { if _, ok := m[key]; !ok { t.Errorf("missing JSON key %q", key) }