diff --git a/Makefile b/Makefile index 939b73ad..cd8d5016 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ lint: .PHONY: gen-spec-schema gen-spec-schema: + # vendor for gen + go mod vendor go run schemagen/main.go # All gen targets diff --git a/csv/spec.go b/csv/spec.go index e1f0b7dc..ad24a266 100644 --- a/csv/spec.go +++ b/csv/spec.go @@ -6,12 +6,13 @@ import ( "github.com/invopop/jsonschema" ) -type Spec struct { +// nolint:revive +type CSVSpec struct { SkipHeader bool `json:"skip_header,omitempty"` Delimiter string `json:"delimiter,omitempty"` } -func (Spec) JSONSchema() *jsonschema.Schema { +func (CSVSpec) JSONSchema() *jsonschema.Schema { properties := jsonschema.NewProperties() properties.Set("skip_header", &jsonschema.Schema{ Type: "boolean", @@ -32,13 +33,13 @@ func (Spec) JSONSchema() *jsonschema.Schema { } } -func (s *Spec) SetDefaults() { +func (s *CSVSpec) SetDefaults() { if s.Delimiter == "" { s.Delimiter = "," } } -func (s *Spec) Validate() error { +func (s *CSVSpec) Validate() error { if len(s.Delimiter) != 1 { return fmt.Errorf("delimiter must be a single character") } diff --git a/csv/spec_test.go b/csv/spec_test.go index a274d56a..7206e800 100644 --- a/csv/spec_test.go +++ b/csv/spec_test.go @@ -8,7 +8,7 @@ import ( ) func TestSpec_JSONSchema(t *testing.T) { - schema, err := jsonschema.Generate(Spec{}) + schema, err := jsonschema.Generate(CSVSpec{}) require.NoError(t, err) jsonschema.TestJSONSchema(t, string(schema), []jsonschema.TestCase{ diff --git a/json/spec.go b/json/spec.go index 6024245c..1fe6cc86 100644 --- a/json/spec.go +++ b/json/spec.go @@ -2,9 +2,10 @@ package json import "github.com/invopop/jsonschema" -type Spec struct{} +// nolint:revive +type JSONSpec struct{} -func (Spec) JSONSchema() *jsonschema.Schema { +func (JSONSpec) JSONSchema() *jsonschema.Schema { return &jsonschema.Schema{ Description: "CloudQuery JSON file output spec.", Type: "object", @@ -12,8 +13,8 @@ func (Spec) JSONSchema() *jsonschema.Schema { } } -func (*Spec) SetDefaults() {} +func (*JSONSpec) SetDefaults() {} -func (*Spec) Validate() error { +func (*JSONSpec) Validate() error { return nil } diff --git a/json/spec_test.go b/json/spec_test.go index 7dbe6dc6..47778326 100644 --- a/json/spec_test.go +++ b/json/spec_test.go @@ -8,7 +8,7 @@ import ( ) func TestSpec_JSONSchema(t *testing.T) { - schema, err := jsonschema.Generate(Spec{}) + schema, err := jsonschema.Generate(JSONSpec{}) require.NoError(t, err) jsonschema.TestJSONSchema(t, string(schema), []jsonschema.TestCase{ diff --git a/parquet/client.go b/parquet/client.go index 73a462f9..418df2bd 100644 --- a/parquet/client.go +++ b/parquet/client.go @@ -4,7 +4,7 @@ type Options func(*Client) // Client is a parquet client. type Client struct { - spec Spec + spec ParquetSpec } func NewClient(options ...Options) (*Client, error) { @@ -16,7 +16,7 @@ func NewClient(options ...Options) (*Client, error) { return c, nil } -func WithSpec(spec Spec) Options { +func WithSpec(spec ParquetSpec) Options { return func(c *Client) { c.spec = spec } diff --git a/parquet/spec.go b/parquet/spec.go index 272b014f..4cdc4c63 100644 --- a/parquet/spec.go +++ b/parquet/spec.go @@ -2,9 +2,10 @@ package parquet import "github.com/invopop/jsonschema" -type Spec struct{} +// nolint:revive +type ParquetSpec struct{} -func (Spec) JSONSchema() *jsonschema.Schema { +func (ParquetSpec) JSONSchema() *jsonschema.Schema { return &jsonschema.Schema{ Description: "CloudQuery Parquet file output spec.", Type: "object", @@ -12,9 +13,9 @@ func (Spec) JSONSchema() *jsonschema.Schema { } } -func (*Spec) SetDefaults() { +func (*ParquetSpec) SetDefaults() { } -func (*Spec) Validate() error { +func (*ParquetSpec) Validate() error { return nil } diff --git a/parquet/spec_test.go b/parquet/spec_test.go index a1436978..9b619a5f 100644 --- a/parquet/spec_test.go +++ b/parquet/spec_test.go @@ -8,7 +8,7 @@ import ( ) func TestSpec_JSONSchema(t *testing.T) { - schema, err := jsonschema.Generate(Spec{}) + schema, err := jsonschema.Generate(ParquetSpec{}) require.NoError(t, err) jsonschema.TestJSONSchema(t, string(schema), []jsonschema.TestCase{ diff --git a/schema.go b/schema.go index 84b3dd58..1c0e9254 100644 --- a/schema.go +++ b/schema.go @@ -20,9 +20,9 @@ func (FileSpec) JSONSchemaOptions() []cqjsonschema.Option { return nil } return reflect.VisibleFields(reflect.TypeOf(struct { - CSVSpec csv.Spec - JSONSpec jsonfile.Spec - ParquetSpec parquet.Spec + CSVSpec csv.CSVSpec + JSONSpec jsonfile.JSONSpec + ParquetSpec parquet.ParquetSpec }{})) } if r.AdditionalFields == nil { diff --git a/schema.json b/schema.json index cc2193cd..1554e8e3 100644 --- a/schema.json +++ b/schema.json @@ -3,6 +3,24 @@ "$id": "https://github.com/cloudquery/filetypes/v4/file-spec", "$ref": "#/$defs/FileSpec", "$defs": { + "CSVSpec": { + "properties": { + "skip_header": { + "type": "boolean", + "description": "Specifies if the first line of a file should be the header.", + "default": false + }, + "delimiter": { + "type": "string", + "pattern": "^.$", + "description": "Character that will be used as the delimiter.", + "default": "," + } + }, + "additionalProperties": false, + "type": "object", + "description": "CloudQuery CSV file output spec." + }, "FileSpec": { "oneOf": [ { @@ -14,7 +32,7 @@ "format_spec": { "oneOf": [ { - "$ref": "#/$defs/Spec" + "$ref": "#/$defs/CSVSpec" }, { "type": "null" @@ -32,7 +50,7 @@ "format_spec": { "oneOf": [ { - "$ref": "#/$defs/Spec-1" + "$ref": "#/$defs/JSONSpec" }, { "type": "null" @@ -50,7 +68,7 @@ "format_spec": { "oneOf": [ { - "$ref": "#/$defs/Spec-2" + "$ref": "#/$defs/ParquetSpec" }, { "type": "null" @@ -75,13 +93,13 @@ { "anyOf": [ { - "$ref": "#/$defs/Spec" + "$ref": "#/$defs/CSVSpec" }, { - "$ref": "#/$defs/Spec-1" + "$ref": "#/$defs/JSONSpec" }, { - "$ref": "#/$defs/Spec-2" + "$ref": "#/$defs/ParquetSpec" } ] }, @@ -105,30 +123,12 @@ "format" ] }, - "Spec": { - "properties": { - "skip_header": { - "type": "boolean", - "description": "Specifies if the first line of a file should be the header.", - "default": false - }, - "delimiter": { - "type": "string", - "pattern": "^.$", - "description": "Character that will be used as the delimiter.", - "default": "," - } - }, - "additionalProperties": false, - "type": "object", - "description": "CloudQuery CSV file output spec." - }, - "Spec-1": { + "JSONSpec": { "additionalProperties": false, "type": "object", "description": "CloudQuery JSON file output spec." }, - "Spec-2": { + "ParquetSpec": { "additionalProperties": false, "type": "object", "description": "CloudQuery Parquet file output spec." diff --git a/spec.go b/spec.go index a76d8f9d..7c72f54e 100644 --- a/spec.go +++ b/spec.go @@ -37,9 +37,9 @@ type FileSpec struct { // Empty or missing stands for no compression. Compression CompressionType `json:"compression,omitempty" jsonschema:"enum=,enum=gzip"` - csvSpec *csv.Spec - jsonSpec *jsonfile.Spec - parquetSpec *parquet.Spec + csvSpec *csv.CSVSpec + jsonSpec *jsonfile.JSONSpec + parquetSpec *parquet.ParquetSpec } func (s *FileSpec) SetDefaults() { @@ -87,13 +87,13 @@ func (s *FileSpec) UnmarshalSpec() error { switch s.Format { case FormatTypeCSV: - s.csvSpec = &csv.Spec{} + s.csvSpec = &csv.CSVSpec{} return dec.Decode(s.csvSpec) case FormatTypeJSON: - s.jsonSpec = &jsonfile.Spec{} + s.jsonSpec = &jsonfile.JSONSpec{} return dec.Decode(s.jsonSpec) case FormatTypeParquet: - s.parquetSpec = &parquet.Spec{} + s.parquetSpec = &parquet.ParquetSpec{} return dec.Decode(s.parquetSpec) default: return fmt.Errorf("unknown format %s", s.Format) diff --git a/spec_test.go b/spec_test.go index 54e593ca..e310724d 100644 --- a/spec_test.go +++ b/spec_test.go @@ -11,10 +11,10 @@ import ( func TestSpecMethods(t *testing.T) { testCases := []struct { FileSpec *FileSpec - preDefaultsCSV *csv.Spec - preDefaultsJSON *json.Spec - postDefaultsCSV *csv.Spec - postDefaultsJSON *json.Spec + preDefaultsCSV *csv.CSVSpec + preDefaultsJSON *json.JSONSpec + postDefaultsCSV *csv.CSVSpec + postDefaultsJSON *json.JSONSpec expectError bool }{ { @@ -22,8 +22,8 @@ func TestSpecMethods(t *testing.T) { Format: FormatTypeCSV, FormatSpec: map[string]any{}, }, - preDefaultsCSV: &csv.Spec{}, - postDefaultsCSV: &csv.Spec{ + preDefaultsCSV: &csv.CSVSpec{}, + postDefaultsCSV: &csv.CSVSpec{ SkipHeader: false, Delimiter: ",", }, @@ -36,11 +36,11 @@ func TestSpecMethods(t *testing.T) { "skip_header": true, }, }, - preDefaultsCSV: &csv.Spec{ + preDefaultsCSV: &csv.CSVSpec{ SkipHeader: true, Delimiter: ",", }, - postDefaultsCSV: &csv.Spec{ + postDefaultsCSV: &csv.CSVSpec{ SkipHeader: true, Delimiter: ",", }, @@ -50,11 +50,11 @@ func TestSpecMethods(t *testing.T) { Format: FormatTypeCSV, FormatSpec: map[string]any{}, }, - preDefaultsCSV: &csv.Spec{ + preDefaultsCSV: &csv.CSVSpec{ SkipHeader: false, Delimiter: "", }, - postDefaultsCSV: &csv.Spec{ + postDefaultsCSV: &csv.CSVSpec{ SkipHeader: false, Delimiter: ",", }, @@ -63,8 +63,8 @@ func TestSpecMethods(t *testing.T) { FileSpec: &FileSpec{ Format: FormatTypeJSON, }, - preDefaultsJSON: &json.Spec{}, - postDefaultsJSON: &json.Spec{}, + preDefaultsJSON: &json.JSONSpec{}, + postDefaultsJSON: &json.JSONSpec{}, }, {