diff --git a/cmd/relspec/convert.go b/cmd/relspec/convert.go index b0e4e5a..08c798a 100644 --- a/cmd/relspec/convert.go +++ b/cmd/relspec/convert.go @@ -181,7 +181,7 @@ func init() { convertCmd.Flags().BoolVar(&convertFlattenSchema, "flatten-schema", false, "Flatten schema.table names to schema_table (useful for databases like SQLite that do not support schemas)") convertCmd.Flags().StringVar(&convertNullableTypes, "types", "", "Nullable type package for code-gen writers (bun/gorm): 'baselib' (default, Go pointer types), 'stdlib' (database/sql), or 'sqltypes'") convertCmd.Flags().BoolVar(&convertContinueOnError, "continue-on-error", false, "Prepend \\set ON_ERROR_STOP off to generated SQL so psql continues past errors (pgsql output only)") - convertCmd.Flags().StringVar(&convertExtraFields, "extra-fields", "", "JSON array of extra Bun model fields to inject (bun output only); fields support target_table, name, type, bun_tag, json_tag, comment") + convertCmd.Flags().StringVar(&convertExtraFields, "extra-fields", "", "Path to JSON file containing extra Bun model fields to inject (bun output only); fields support target_table, name, type, bun_tag, json_tag, comment") err := convertCmd.MarkFlagRequired("from") if err != nil { @@ -396,15 +396,20 @@ func writeDatabase(db *models.Database, dbType, outputPath, packageName, schemaF if strings.ToLower(dbType) != "bun" { return fmt.Errorf("--extra-fields is only supported for Bun output") } + extraFieldsJSON, err := os.ReadFile(extraFields) + if err != nil { + return fmt.Errorf("failed to read --extra-fields file %q: %w", extraFields, err) + } + var parsed []wbun.ExtraFieldConfig - if err := stdjson.Unmarshal([]byte(extraFields), &parsed); err != nil { - return fmt.Errorf("invalid --extra-fields JSON: %w", err) + if err := stdjson.Unmarshal(extraFieldsJSON, &parsed); err != nil { + return fmt.Errorf("invalid --extra-fields JSON in %q: %w", extraFields, err) } if len(parsed) == 0 { return fmt.Errorf("--extra-fields must contain at least one field") } writerOpts.Metadata = map[string]interface{}{ - "extra_fields": extraFields, + "extra_fields": string(extraFieldsJSON), } } diff --git a/pkg/writers/bun/README.md b/pkg/writers/bun/README.md index e427362..e580865 100644 --- a/pkg/writers/bun/README.md +++ b/pkg/writers/bun/README.md @@ -67,9 +67,10 @@ relspec convert --from json --from-path schema.json \ --to bun --to-path models/ --package models # Inject computed/scan-only fields that are not present in the database schema +# (extra-fields.json contains the JSON array shown below) relspec convert --from dbml --from-path schema.dbml \ --to bun --to-path models.go --package models \ - --extra-fields '[{"target_table":"projects","name":"ThoughtCount","type":"sql_types.SqlInt64","bun_tag":"thought_count,scanonly","json_tag":"thought_count"}]' + --extra-fields extra-fields.json ``` ## Generated Code Examples @@ -189,11 +190,14 @@ options := &writers.WriterOptions{ #### Extra fields -Use `Metadata["extra_fields"]` (or the CLI `--extra-fields` flag) to inject +Use `Metadata["extra_fields"]` (or the CLI `--extra-fields ` flag) to inject custom fields into generated Bun models without editing generated files. This is intended for computed columns and scan-only query fields that Bun must scan into but that are not real database table columns. +The CLI flag expects a path to a JSON file, not inline JSON. This avoids shell +quoting problems with struct tags and complex type names. + Each entry supports: | Field | Required | Description | @@ -224,6 +228,21 @@ options := &writers.WriterOptions{ } ``` +Example `extra-fields.json`: + +```json +[ + { + "target_table": "projects", + "name": "ThoughtCount", + "type": "sql_types.SqlInt64", + "bun_tag": "thought_count,scanonly", + "json_tag": "thought_count", + "comment": "Computed by ResolveSpec queries" + } +] +``` + ## Notes - Model names are derived from table names (singularized, PascalCase)