diff --git a/.github/workflows/schema-update.yml b/.github/workflows/schema-update.yml index df556aac..46949817 100644 --- a/.github/workflows/schema-update.yml +++ b/.github/workflows/schema-update.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/setup-go@v5 with: go-version-file: go.mod - - run: go run . schema > .github/crush-schema.json + - run: go run . schema > ./schema.json - uses: stefanzweifel/git-auto-commit-action@778341af668090896ca464160c2def5d1d1a3eb0 # v5 with: commit_message: "chore: auto-update generated files" diff --git a/internal/cmd/schema.go b/internal/cmd/schema.go index 59b0ae90..f835e250 100644 --- a/internal/cmd/schema.go +++ b/internal/cmd/schema.go @@ -3,7 +3,6 @@ package cmd import ( "encoding/json" "fmt" - "reflect" "github.com/charmbracelet/crush/internal/config" "github.com/invopop/jsonschema" @@ -16,52 +15,12 @@ var schemaCmd = &cobra.Command{ Long: "Generate JSON schema for the crush configuration file", Hidden: true, RunE: func(cmd *cobra.Command, args []string) error { - reflector := jsonschema.Reflector{ - // Custom type mapper to handle csync.Map - Mapper: func(t reflect.Type) *jsonschema.Schema { - // Handle csync.Map[string, ProviderConfig] specifically - if t.String() == "csync.Map[string,github.com/charmbracelet/crush/internal/config.ProviderConfig]" { - return &jsonschema.Schema{ - Type: "object", - Description: "AI provider configurations", - AdditionalProperties: &jsonschema.Schema{ - Ref: "#/$defs/ProviderConfig", - }, - } - } - return nil - }, - } - - // First reflect the config to get the main schema - schema := reflector.Reflect(&config.Config{}) - - // Now manually add the ProviderConfig definition that might be missing - providerConfigSchema := reflector.ReflectFromType(reflect.TypeOf(config.ProviderConfig{})) - if schema.Definitions == nil { - schema.Definitions = make(map[string]*jsonschema.Schema) - } - - // Extract the actual definition from the nested schema - if providerConfigSchema.Definitions != nil && providerConfigSchema.Definitions["ProviderConfig"] != nil { - schema.Definitions["ProviderConfig"] = providerConfigSchema.Definitions["ProviderConfig"] - // Also add any other definitions from the provider config schema - for k, v := range providerConfigSchema.Definitions { - if k != "ProviderConfig" { - schema.Definitions[k] = v - } - } - } else { - // Fallback: use the schema itself if it's not nested - schema.Definitions["ProviderConfig"] = providerConfigSchema - } - - schemaJSON, err := json.MarshalIndent(schema, "", " ") + reflector := new(jsonschema.Reflector) + bts, err := json.MarshalIndent(reflector.Reflect(&config.Config{}), "", " ") if err != nil { return fmt.Errorf("failed to marshal schema: %w", err) } - - fmt.Println(string(schemaJSON)) + fmt.Println(string(bts)) return nil }, } diff --git a/internal/csync/maps.go b/internal/csync/maps.go index 108c8a4c..67796baf 100644 --- a/internal/csync/maps.go +++ b/internal/csync/maps.go @@ -96,6 +96,11 @@ var ( _ json.Marshaler = &Map[string, any]{} ) +func (Map[K, V]) JSONSchemaAlias() any { //nolint + m := map[K]V{} + return m +} + // UnmarshalJSON implements json.Unmarshaler. func (m *Map[K, V]) UnmarshalJSON(data []byte) error { m.mu.Lock() diff --git a/.github/crush-schema.json b/schema.json similarity index 100% rename from .github/crush-schema.json rename to schema.json