Skip to content

Commit 36a6da4

Browse files
committed
feat: added json and bcrypt generators
1 parent 96e782d commit 36a6da4

4 files changed

Lines changed: 143 additions & 3 deletions

File tree

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ require (
99
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b
1010
github.com/pmezard/go-difflib v1.0.0
1111
github.com/spf13/cobra v1.10.1
12+
golang.org/x/crypto v0.31.0
13+
golang.org/x/term v0.39.0
1214
golang.org/x/text v0.28.0
1315
gopkg.in/yaml.v3 v3.0.1
1416
)
@@ -21,9 +23,7 @@ require (
2123
github.com/kr/pretty v0.3.1 // indirect
2224
github.com/spf13/pflag v1.0.10 // indirect
2325
github.com/stretchr/testify v1.11.1 // indirect
24-
golang.org/x/crypto v0.31.0 // indirect
2526
golang.org/x/sync v0.16.0 // indirect
2627
golang.org/x/sys v0.40.0 // indirect
27-
golang.org/x/term v0.39.0 // indirect
2828
gopkg.in/yaml.v2 v2.4.0 // indirect
2929
)

regresql/fixture_manager.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func (fm *FixtureManager) registerBuiltinGenerators() error {
5050
NewDecimalGenerator(),
5151
NewBoolGenerator(),
5252
NewRangeGenerator(),
53+
NewBcryptHashGenerator(),
5354
}
5455

5556
for _, gen := range basicGens {
@@ -62,6 +63,7 @@ func (fm *FixtureManager) registerBuiltinGenerators() error {
6263
NewForeignKeyGenerator(fm.db),
6364
NewPatternGenerator(fm.generators),
6465
NewTemplateGenerator(fm.generators),
66+
NewJSONGenerator(fm.generators),
6567
}
6668

6769
for _, gen := range advancedGens {
@@ -549,7 +551,11 @@ func (fm *FixtureManager) autoDetectForeignKeys(genSpec *GenerateSpec, tableInfo
549551
// Helper functions
550552

551553
func joinColumns(columns []string) string {
552-
return joinStrings(columns, ", ")
554+
quoted := make([]string, len(columns))
555+
for i, col := range columns {
556+
quoted[i] = `"` + col + `"`
557+
}
558+
return joinStrings(quoted, ", ")
553559
}
554560

555561
func joinStrings(strs []string, sep string) string {

regresql/generators_basic.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
"github.com/google/uuid"
9+
"golang.org/x/crypto/bcrypt"
910
)
1011

1112
const defaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
@@ -96,6 +97,11 @@ type (
9697
BoolGenerator struct {
9798
BaseGenerator
9899
}
100+
101+
// BcryptHashGenerator generates bcrypt password hashes
102+
BcryptHashGenerator struct {
103+
BaseGenerator
104+
}
99105
)
100106

101107
func NewSequenceGenerator() *SequenceGenerator {
@@ -517,3 +523,35 @@ func (g *BoolGenerator) Validate(params map[string]any, column *ColumnInfo) erro
517523
}
518524
return nil
519525
}
526+
527+
func NewBcryptHashGenerator() *BcryptHashGenerator {
528+
return &BcryptHashGenerator{
529+
BaseGenerator: BaseGenerator{name: "bcrypt_hash"},
530+
}
531+
}
532+
533+
func (g *BcryptHashGenerator) Generate(params map[string]any, column *ColumnInfo) (any, error) {
534+
password, err := getRequiredParam[string](params, "password")
535+
if err != nil {
536+
return nil, err
537+
}
538+
cost := getParam(params, "cost", 10)
539+
540+
hash, err := bcrypt.GenerateFromPassword([]byte(password), cost)
541+
if err != nil {
542+
return nil, fmt.Errorf("bcrypt hash generation failed: %w", err)
543+
}
544+
return string(hash), nil
545+
}
546+
547+
func (g *BcryptHashGenerator) Validate(params map[string]any, column *ColumnInfo) error {
548+
if _, err := getRequiredParam[string](params, "password"); err != nil {
549+
return fmt.Errorf("bcrypt_hash requires 'password' parameter")
550+
}
551+
552+
cost := getParam(params, "cost", 10)
553+
if cost < bcrypt.MinCost || cost > bcrypt.MaxCost {
554+
return fmt.Errorf("bcrypt cost must be between %d and %d, got %d", bcrypt.MinCost, bcrypt.MaxCost, cost)
555+
}
556+
return nil
557+
}

regresql/generators_json.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package regresql
2+
3+
import "fmt"
4+
5+
type JSONGenerator struct {
6+
registry *GeneratorRegistry
7+
}
8+
9+
func NewJSONGenerator(registry *GeneratorRegistry) *JSONGenerator {
10+
return &JSONGenerator{registry: registry}
11+
}
12+
13+
func (g *JSONGenerator) Name() string { return "json" }
14+
15+
func (g *JSONGenerator) Validate(params map[string]any, column *ColumnInfo) error {
16+
_, hasSchema := params["schema"]
17+
_, hasValue := params["value"]
18+
19+
if !hasSchema && !hasValue {
20+
return fmt.Errorf("json generator requires either 'schema' or 'value' parameter")
21+
}
22+
if hasSchema && hasValue {
23+
return fmt.Errorf("json generator cannot have both 'schema' and 'value'")
24+
}
25+
26+
if hasSchema {
27+
schema, ok := params["schema"].(map[string]any)
28+
if !ok {
29+
return fmt.Errorf("'schema' must be an object")
30+
}
31+
return g.validateSchema(schema)
32+
}
33+
return nil
34+
}
35+
36+
func (g *JSONGenerator) validateSchema(schema map[string]any) error {
37+
for field, spec := range schema {
38+
specMap, ok := spec.(map[string]any)
39+
if !ok {
40+
continue // static value
41+
}
42+
43+
genName, ok := specMap["generator"].(string)
44+
if !ok {
45+
continue // static value (object without generator key)
46+
}
47+
48+
gen, err := g.registry.Get(genName)
49+
if err != nil {
50+
return fmt.Errorf("field '%s': %w", field, err)
51+
}
52+
53+
if err := gen.Validate(specMap, nil); err != nil {
54+
return fmt.Errorf("field '%s': %w", field, err)
55+
}
56+
}
57+
return nil
58+
}
59+
60+
func (g *JSONGenerator) Generate(params map[string]any, column *ColumnInfo) (any, error) {
61+
// Static value mode
62+
if value, ok := params["value"]; ok {
63+
return value, nil
64+
}
65+
66+
// Schema mode
67+
schema := params["schema"].(map[string]any)
68+
result := make(map[string]any)
69+
70+
for field, spec := range schema {
71+
specMap, ok := spec.(map[string]any)
72+
if !ok {
73+
result[field] = spec
74+
continue
75+
}
76+
77+
genName, ok := specMap["generator"].(string)
78+
if !ok {
79+
result[field] = spec
80+
continue
81+
}
82+
83+
gen, err := g.registry.Get(genName)
84+
if err != nil {
85+
return nil, fmt.Errorf("field '%s': %w", field, err)
86+
}
87+
88+
value, err := gen.Generate(specMap, nil)
89+
if err != nil {
90+
return nil, fmt.Errorf("field '%s': %w", field, err)
91+
}
92+
result[field] = value
93+
}
94+
95+
return result, nil
96+
}

0 commit comments

Comments
 (0)