mirror of
https://github.com/therootcompany/golib.git
synced 2026-03-13 12:27:59 +00:00
Separate library from CLI concerns: - Add Resolver callback type with Decision/Response structs for all interactive decisions (map/struct, type name, tuple/list, shape unification, shape naming, name collision) - Move terminal I/O (Prompter) from library to cmd/jsonpaths - Add public API: New(), ParseFormat(), Generate(), AutoGenerate() - Add Format type with aliases (ts, py, json-paths, etc.) - Fix godoc comments to match exported function names - Update tests to use scriptedResolver instead of Prompter internals - Update doc.go and README with current API
118 lines
3.5 KiB
Go
118 lines
3.5 KiB
Go
package jsontypes
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Format identifies a target output format for type generation.
|
|
type Format string
|
|
|
|
const (
|
|
FormatGo Format = "go"
|
|
FormatTypeScript Format = "typescript"
|
|
FormatJSDoc Format = "jsdoc"
|
|
FormatZod Format = "zod"
|
|
FormatPython Format = "python"
|
|
FormatSQL Format = "sql"
|
|
FormatJSONSchema Format = "jsonschema"
|
|
FormatTypedef Format = "typedef"
|
|
FormatFlatPaths Format = "paths"
|
|
)
|
|
|
|
// Options configures AutoGenerate behavior.
|
|
type Options struct {
|
|
// Format selects the output format (default: FormatFlatPaths).
|
|
Format Format
|
|
|
|
// Resolver handles interactive decisions during analysis.
|
|
// If nil, heuristic defaults are used (fully autonomous).
|
|
Resolver Resolver
|
|
|
|
// AskTypes prompts for every type name, even when heuristics
|
|
// are confident. Only meaningful when Resolver is set.
|
|
AskTypes bool
|
|
}
|
|
|
|
// ParseFormat normalizes a format string, accepting common aliases.
|
|
// Returns an error for unrecognized formats.
|
|
func ParseFormat(s string) (Format, error) {
|
|
if f, ok := formatAliases[s]; ok {
|
|
return f, nil
|
|
}
|
|
return "", fmt.Errorf("unknown format: %q (use: paths, go, typescript, jsdoc, zod, python, sql, jsonschema, typedef)", s)
|
|
}
|
|
|
|
var formatAliases = map[string]Format{
|
|
"": FormatFlatPaths,
|
|
"paths": FormatFlatPaths,
|
|
"json-paths": FormatFlatPaths,
|
|
"go": FormatGo,
|
|
"typescript": FormatTypeScript,
|
|
"ts": FormatTypeScript,
|
|
"jsdoc": FormatJSDoc,
|
|
"zod": FormatZod,
|
|
"python": FormatPython,
|
|
"py": FormatPython,
|
|
"sql": FormatSQL,
|
|
"jsonschema": FormatJSONSchema,
|
|
"json-schema": FormatJSONSchema,
|
|
"typedef": FormatTypedef,
|
|
"json-typedef": FormatTypedef,
|
|
}
|
|
|
|
// Generate renders formatted paths into the given output format.
|
|
// Use FormatFlatPaths to get the intermediate path notation.
|
|
func Generate(format Format, paths []string) (string, error) {
|
|
if format == FormatFlatPaths {
|
|
return strings.Join(paths, "\n") + "\n", nil
|
|
}
|
|
gen, ok := generators[format]
|
|
if !ok {
|
|
return "", fmt.Errorf("unknown format: %q", format)
|
|
}
|
|
return gen(paths), nil
|
|
}
|
|
|
|
// AutoGenerate parses JSON from raw bytes and generates type definitions.
|
|
func AutoGenerate(data []byte, opts Options) (string, error) {
|
|
var v any
|
|
dec := json.NewDecoder(bytes.NewReader(data))
|
|
dec.UseNumber()
|
|
if err := dec.Decode(&v); err != nil {
|
|
return "", fmt.Errorf("invalid JSON: %w", err)
|
|
}
|
|
return AutoGenerateFromAny(v, opts)
|
|
}
|
|
|
|
// AutoGenerateFromString parses a JSON string and generates type definitions.
|
|
func AutoGenerateFromString(s string, opts Options) (string, error) {
|
|
return AutoGenerate([]byte(s), opts)
|
|
}
|
|
|
|
// AutoGenerateFromAny generates type definitions from an already-decoded JSON
|
|
// value. The value must have been decoded with json.UseNumber() so that
|
|
// integers and floats are distinguishable.
|
|
func AutoGenerateFromAny(v any, opts Options) (string, error) {
|
|
a := New(AnalyzerConfig{Resolver: opts.Resolver, AskTypes: opts.AskTypes})
|
|
paths := FormatPaths(a.Analyze(".", v))
|
|
format := opts.Format
|
|
if format == "" {
|
|
format = FormatFlatPaths
|
|
}
|
|
return Generate(format, paths)
|
|
}
|
|
|
|
var generators = map[Format]func([]string) string{
|
|
FormatGo: GenerateGoStructs,
|
|
FormatTypeScript: GenerateTypeScript,
|
|
FormatJSDoc: GenerateJSDoc,
|
|
FormatZod: GenerateZod,
|
|
FormatPython: GeneratePython,
|
|
FormatSQL: GenerateSQL,
|
|
FormatJSONSchema: GenerateJSONSchema,
|
|
FormatTypedef: GenerateTypedef,
|
|
}
|