blueprinter_schema 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AGENTS.md +23 -0
- data/README.md +29 -3
- data/lib/blueprinter_schema/generator.rb +17 -11
- data/lib/blueprinter_schema/version.rb +1 -1
- data/lib/blueprinter_schema.rb +4 -3
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0cafd732029c0e4f3cd09d13dd6809e3e68f599c194a24247774e7d18f6233ca
|
|
4
|
+
data.tar.gz: 1bf4791a3812e9f16bd3c8d7f8ed0bc2a91095130b91286fa75d3b72954b1482
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 02577f5a4da542def621be3544ff1c82d4509addfc2b8b7a1264a9a6e7d079943ae75c0574f160354f48ebf3c6b1481eeb09d899a35fb3ed83b169e25671a482
|
|
7
|
+
data.tar.gz: 6690022f62b1a2ad817a362ae2322300e0013c22494b1bb2efe195478c0a6036063c3c31ae422ab92b1745591cacdf4d6aba0356e386df32d1419f28c8ecb717
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# BlueprinterSchema
|
|
2
|
+
|
|
3
|
+
A gem to create JSON Schemas from [Blueprinter](https://github.com/procore-oss/blueprinter) Serializers.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
- Specs MUST assert the full expected schema, so that they serve as clear documentation of what is generated
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
### Setup
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
mise install
|
|
15
|
+
bin/setup
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Test, lint
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
bundle exec rspec
|
|
22
|
+
bundle exec rubocop -A
|
|
23
|
+
```
|
data/README.md
CHANGED
|
@@ -18,6 +18,8 @@ class UserSerializer < Blueprinter::Base
|
|
|
18
18
|
field :last_name, type: [:string, :null]
|
|
19
19
|
field :full_name, type: [:string, :null], description: "The concatendated first and last name."
|
|
20
20
|
field :email, type: :string, format: :email
|
|
21
|
+
field :role, type: :string, enum: ["user", "admin"]
|
|
22
|
+
field :tags, type: :array, items: { type: :string }
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
BlueprinterSchema.generate(serializer: UserSerializer)
|
|
@@ -40,9 +42,17 @@ BlueprinterSchema.generate(serializer: UserSerializer)
|
|
|
40
42
|
"email" => {
|
|
41
43
|
"type" => "string",
|
|
42
44
|
"format" => "email"
|
|
45
|
+
},
|
|
46
|
+
"role" => {
|
|
47
|
+
"type" => "string",
|
|
48
|
+
"enum" => ["user", "admin"]
|
|
49
|
+
},
|
|
50
|
+
"tags" => {
|
|
51
|
+
"type" => "array",
|
|
52
|
+
"items" => { "type" => "string" }
|
|
43
53
|
}
|
|
44
54
|
},
|
|
45
|
-
"required" => ["first_name", "last_name", "full_name", "email"],
|
|
55
|
+
"required" => ["first_name", "last_name", "full_name", "email", "role", "tags"],
|
|
46
56
|
"additionalProperties" => false
|
|
47
57
|
}
|
|
48
58
|
```
|
|
@@ -90,6 +100,7 @@ class UserSerializer < Blueprinter::Base
|
|
|
90
100
|
|
|
91
101
|
association :addresses, blueprint: AddressSerializer, collection: true
|
|
92
102
|
association :profile, blueprint: ProfileSerializer
|
|
103
|
+
association :account, blueprint: AccountSerializer, optional: true
|
|
93
104
|
end
|
|
94
105
|
|
|
95
106
|
class AddressSerializer < Blueprinter::Base
|
|
@@ -100,6 +111,10 @@ class ProfileSerializer < Blueprinter::Base
|
|
|
100
111
|
field :public, type: :boolean
|
|
101
112
|
end
|
|
102
113
|
|
|
114
|
+
class AccountSerializer < Blueprinter::Base
|
|
115
|
+
field :name, type: :string
|
|
116
|
+
end
|
|
117
|
+
|
|
103
118
|
BlueprinterSchema.generate(serializer: UserSerializer)
|
|
104
119
|
```
|
|
105
120
|
|
|
@@ -132,6 +147,16 @@ BlueprinterSchema.generate(serializer: UserSerializer)
|
|
|
132
147
|
},
|
|
133
148
|
"required" => ["public"],
|
|
134
149
|
"additionalProperties" => false
|
|
150
|
+
},
|
|
151
|
+
"account" => {
|
|
152
|
+
"type" => ["object", "null"],
|
|
153
|
+
"properties" => {
|
|
154
|
+
"name" => {
|
|
155
|
+
"type" => "string"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"required" => ["name"],
|
|
159
|
+
"additionalProperties" => false
|
|
135
160
|
}
|
|
136
161
|
},
|
|
137
162
|
"required" => ["email", "addresses", "profile"],
|
|
@@ -146,8 +171,9 @@ BlueprinterSchema.generate(
|
|
|
146
171
|
serializer:,
|
|
147
172
|
model: nil,
|
|
148
173
|
include_conditional_fields: true, # Whether or not to include conditional fields from the serializer
|
|
149
|
-
|
|
150
|
-
view: :default # The blueprint view to use
|
|
174
|
+
fallback_definition: {}, # Type when no DB column or type definition is found. E.g. { 'type' => 'object' }
|
|
175
|
+
view: :default, # The blueprint view to use
|
|
176
|
+
type: "object" # Root type
|
|
151
177
|
)
|
|
152
178
|
```
|
|
153
179
|
|
|
@@ -5,17 +5,18 @@ module BlueprinterSchema
|
|
|
5
5
|
|
|
6
6
|
# rubocop:disable Metrics/ClassLength
|
|
7
7
|
class Generator
|
|
8
|
-
def initialize(serializer:, model:, skip_conditional_fields:, fallback_definition:, view:)
|
|
8
|
+
def initialize(serializer:, model:, skip_conditional_fields:, fallback_definition:, view:, type:) # rubocop:disable Metrics/ParameterLists
|
|
9
9
|
@serializer = serializer
|
|
10
10
|
@model = model
|
|
11
11
|
@skip_conditional_fields = skip_conditional_fields
|
|
12
12
|
@fallback_definition = fallback_definition
|
|
13
13
|
@view = view
|
|
14
|
+
@type = type
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def generate
|
|
17
18
|
schema = {
|
|
18
|
-
'type' =>
|
|
19
|
+
'type' => @type,
|
|
19
20
|
'properties' => build_properties,
|
|
20
21
|
'required' => build_required_fields,
|
|
21
22
|
'additionalProperties' => false
|
|
@@ -63,7 +64,6 @@ module BlueprinterSchema
|
|
|
63
64
|
.keys.map(&:to_s)
|
|
64
65
|
end
|
|
65
66
|
|
|
66
|
-
# rubocop:disable Metrics/AbcSize
|
|
67
67
|
def field_to_json_schema(field)
|
|
68
68
|
type_definition = @fallback_definition.dup
|
|
69
69
|
|
|
@@ -74,12 +74,16 @@ module BlueprinterSchema
|
|
|
74
74
|
type_definition = ar_column_to_json_schema(column)
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
type_definition
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
merge_field_options(type_definition, field.options)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def merge_field_options(type_definition, options)
|
|
81
|
+
type_definition['enum'] = options[:enum] if options[:enum]
|
|
82
|
+
type_definition['items'] = options[:items].deep_stringify_keys if options[:items]
|
|
83
|
+
type_definition['format'] = options[:format] if options[:format]
|
|
84
|
+
type_definition['description'] = options[:description] if options[:description]
|
|
80
85
|
type_definition
|
|
81
86
|
end
|
|
82
|
-
# rubocop:enable Metrics/AbcSize
|
|
83
87
|
|
|
84
88
|
def ensure_valid_json_schema_types!(field)
|
|
85
89
|
types = [field.options[:type]].flatten.map(&:to_s)
|
|
@@ -120,7 +124,7 @@ module BlueprinterSchema
|
|
|
120
124
|
type
|
|
121
125
|
end
|
|
122
126
|
|
|
123
|
-
def association_to_json_schema(association)
|
|
127
|
+
def association_to_json_schema(association) # rubocop:disable Metrics/CyclomaticComplexity
|
|
124
128
|
blueprint_class = association.options[:blueprint]
|
|
125
129
|
|
|
126
130
|
return { 'type' => 'object' } unless blueprint_class
|
|
@@ -129,18 +133,20 @@ module BlueprinterSchema
|
|
|
129
133
|
is_collection = ar_association ? ar_association.collection? : association.options[:collection]
|
|
130
134
|
|
|
131
135
|
view = association.options[:view] || :default
|
|
132
|
-
|
|
136
|
+
type = association.options[:optional] ? %w[object null] : 'object'
|
|
137
|
+
associated_schema = recursive_generate(blueprint_class, ar_association&.klass, view, type:)
|
|
133
138
|
|
|
134
139
|
is_collection ? { 'type' => 'array', 'items' => associated_schema } : associated_schema
|
|
135
140
|
end
|
|
136
141
|
|
|
137
|
-
def recursive_generate(serializer, model, view)
|
|
142
|
+
def recursive_generate(serializer, model, view, type:)
|
|
138
143
|
BlueprinterSchema.generate(
|
|
139
144
|
serializer:,
|
|
140
145
|
model:,
|
|
141
146
|
skip_conditional_fields: @skip_conditional_fields,
|
|
142
147
|
fallback_definition: @fallback_definition,
|
|
143
|
-
view
|
|
148
|
+
view:,
|
|
149
|
+
type:
|
|
144
150
|
)
|
|
145
151
|
end
|
|
146
152
|
end
|
data/lib/blueprinter_schema.rb
CHANGED
|
@@ -4,13 +4,14 @@ require_relative 'blueprinter_schema/version'
|
|
|
4
4
|
require_relative 'blueprinter_schema/generator'
|
|
5
5
|
|
|
6
6
|
module BlueprinterSchema
|
|
7
|
-
def self.generate(
|
|
7
|
+
def self.generate( # rubocop:disable Metrics/ParameterLists
|
|
8
8
|
serializer:,
|
|
9
9
|
model: nil,
|
|
10
10
|
skip_conditional_fields: false,
|
|
11
11
|
fallback_definition: {},
|
|
12
|
-
view: :default
|
|
12
|
+
view: :default,
|
|
13
|
+
type: 'object'
|
|
13
14
|
)
|
|
14
|
-
Generator.new(serializer:, model:, skip_conditional_fields:, fallback_definition:, view:).generate
|
|
15
|
+
Generator.new(serializer:, model:, skip_conditional_fields:, fallback_definition:, view:, type:).generate
|
|
15
16
|
end
|
|
16
17
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: blueprinter_schema
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thisismydesign
|
|
@@ -19,6 +19,7 @@ files:
|
|
|
19
19
|
- ".rspec"
|
|
20
20
|
- ".rubocop.yml"
|
|
21
21
|
- ".tool-versions"
|
|
22
|
+
- AGENTS.md
|
|
22
23
|
- Dockerfile
|
|
23
24
|
- LICENSE.txt
|
|
24
25
|
- README.md
|