types_from_serializers 0.1.2 → 2.0.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/CHANGELOG.md +22 -0
- data/lib/types_from_serializers/dsl.rb +17 -61
- data/lib/types_from_serializers/generator.rb +187 -107
- data/lib/types_from_serializers/railtie.rb +4 -1
- data/lib/types_from_serializers/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 107bcbbe1708fd38efdb7943673c11112350eeee1e457e67e50934641e8081e7
|
|
4
|
+
data.tar.gz: dbb8a8732f99088318ae2d7c16b11dc219bb96357347d1d2174b106216e82599
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d6e0dc57e64062a6934f0e3f336412c897ec4fe5d7497b65536bf45c59c270f39e278fc183f299bfe0cdc6b55769e652d3f6b153bb298bc2f311a0edf2a8e3ad
|
|
7
|
+
data.tar.gz: 00f07fd96b3e9fa907b457969d227e641cfcce1c9e2f67a56bb9f5d9f07b8222d8861144737eb443508ed50024d31992836a3285a1c739e9588817912a6ca168
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## [2.0.0](https://github.com/ElMassimo/types_from_serializers/compare/types_from_serializers@0.1.2...types_from_serializers@2.0.0) (2023-04-02)
|
|
2
|
+
|
|
3
|
+
This version adds support for `oj_serializers-2.0.2`, supporting all changes in:
|
|
4
|
+
|
|
5
|
+
- https://github.com/ElMassimo/oj_serializers/pull/9
|
|
6
|
+
|
|
7
|
+
### Features ✨
|
|
8
|
+
|
|
9
|
+
- Now keys will match the [`transform_keys`](https://github.com/ElMassimo/oj_serializers#transforming-attribute-keys-) configuration instead of always being camelized
|
|
10
|
+
- Support for [`flat_one`](https://github.com/ElMassimo/oj_serializers#composing-serializers-)
|
|
11
|
+
- Use relative paths for imports to make the output configuration more flexible
|
|
12
|
+
- Define the order of properties in the interface with `sort_properties_by`
|
|
13
|
+
|
|
14
|
+
## [0.1.3](https://github.com/ElMassimo/types_from_serializers/compare/types_from_serializers@0.1.2...types_from_serializers@0.1.3) (2022-07-12)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* apply the sql mapping fallback as the default ([64898c4](https://github.com/ElMassimo/types_from_serializers/commit/64898c4e3a3f83ea67294f2200f253cd2a64aea9))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
1
23
|
## [0.1.2](https://github.com/ElMassimo/types_from_serializers/compare/types_from_serializers@0.1.1...types_from_serializers@0.1.2) (2022-07-12)
|
|
2
24
|
|
|
3
25
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "active_support/concern"
|
|
4
4
|
|
|
5
5
|
# Internal: A DSL to specify types for serializer attributes.
|
|
6
|
-
module
|
|
6
|
+
module TypesFromSerializers
|
|
7
7
|
module DSL
|
|
8
8
|
extend ActiveSupport::Concern
|
|
9
9
|
|
|
@@ -16,74 +16,30 @@ module TypesFromSerializer
|
|
|
16
16
|
def object_as(name, model: nil, types_from: nil)
|
|
17
17
|
# NOTE: Avoid taking memory for type information that won't be used.
|
|
18
18
|
if Rails.env.development?
|
|
19
|
-
model ||= name.is_a?(Symbol) ? name : try(:_serializer_model_name)
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
model ||= name.is_a?(Symbol) ? name : try(:_serializer_model_name) || name
|
|
20
|
+
define_singleton_method(:_serializer_model_name) { model }
|
|
21
|
+
define_singleton_method(:_serializer_types_from) { types_from } if types_from
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
super(name)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
# Public:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
_typed_attributes.update(attrs.map { |key, type|
|
|
34
|
-
[key.to_s, type.is_a?(Hash) ? type : {type: type}]
|
|
35
|
-
}.to_h)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# Public: Allows to specify the type for a serializer method that will
|
|
40
|
-
# be defined immediately after calling this method.
|
|
41
|
-
def type(type = :unknown, optional: false)
|
|
42
|
-
@_current_attribute_type = {type: type, optional: optional}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Internal: Intercept a method definition, tying a type that was
|
|
46
|
-
# previously specified to the name of the attribute.
|
|
47
|
-
def method_added(name)
|
|
48
|
-
super(name)
|
|
49
|
-
if @_current_attribute_type
|
|
50
|
-
serializer_attributes name
|
|
51
|
-
|
|
52
|
-
# NOTE: Avoid taking memory for type information that won't be used.
|
|
53
|
-
if Rails.env.development?
|
|
54
|
-
_typed_attributes[name.to_s] = @_current_attribute_type
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
@_current_attribute_type = nil
|
|
58
|
-
end
|
|
27
|
+
# Public: Shortcut for typing a serializer attribute.
|
|
28
|
+
#
|
|
29
|
+
# It specifies the type for a serializer method that will be defined
|
|
30
|
+
# immediately after calling this method.
|
|
31
|
+
def type(type, **options)
|
|
32
|
+
attribute type: type, **options
|
|
59
33
|
end
|
|
60
34
|
|
|
61
|
-
|
|
62
|
-
if Rails.env.development?
|
|
63
|
-
# Internal: Contains type information for serializer attributes.
|
|
64
|
-
def _typed_attributes
|
|
65
|
-
unless defined?(@_typed_attributes)
|
|
66
|
-
@_typed_attributes = superclass.try(:_typed_attributes)&.dup || {}
|
|
67
|
-
end
|
|
68
|
-
@_typed_attributes
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Internal: The name of the model that will be serialized by this
|
|
72
|
-
# serializer, used to infer field types from the SQL columns.
|
|
73
|
-
def _serializer_model_name
|
|
74
|
-
unless defined?(@_serializer_model_name)
|
|
75
|
-
@_serializer_model_name = superclass.try(:_serializer_model_name)
|
|
76
|
-
end
|
|
77
|
-
@_serializer_model_name
|
|
78
|
-
end
|
|
35
|
+
private
|
|
79
36
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@_serializer_types_from
|
|
37
|
+
# Override: Remove unnecessary options in production, types are only
|
|
38
|
+
# used when generating code in development.
|
|
39
|
+
unless Rails.env.development?
|
|
40
|
+
def add_attribute(name, options)
|
|
41
|
+
options.except!(:type, :optional)
|
|
42
|
+
super
|
|
87
43
|
end
|
|
88
44
|
end
|
|
89
45
|
end
|
|
@@ -6,32 +6,7 @@ require "pathname"
|
|
|
6
6
|
|
|
7
7
|
# Public: Automatically generates TypeScript interfaces for Ruby serializers.
|
|
8
8
|
module TypesFromSerializers
|
|
9
|
-
|
|
10
|
-
Config = Struct.new(
|
|
11
|
-
:base_serializers,
|
|
12
|
-
:serializers_dirs,
|
|
13
|
-
:output_dir,
|
|
14
|
-
:name_from_serializer,
|
|
15
|
-
:native_types,
|
|
16
|
-
:sql_to_typescript_type_mapping,
|
|
17
|
-
keyword_init: true,
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
# Internal: The type metadata for a serializer.
|
|
21
|
-
SerializerMetadata = Struct.new(
|
|
22
|
-
:attributes,
|
|
23
|
-
:associations,
|
|
24
|
-
:model_name,
|
|
25
|
-
:types_from,
|
|
26
|
-
keyword_init: true,
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
# Internal: The type metadata for a serializer field.
|
|
30
|
-
FieldMetadata = Struct.new(:name, :type, :optional, :many, keyword_init: true) do
|
|
31
|
-
def typescript_name
|
|
32
|
-
name.to_s.camelize(:lower)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
9
|
+
DEFAULT_TRANSFORM_KEYS = ->(key) { key.camelize(:lower).chomp("?") }
|
|
35
10
|
|
|
36
11
|
# Internal: Extensions that simplify the implementation of the generator.
|
|
37
12
|
module SerializerRefinements
|
|
@@ -54,91 +29,185 @@ module TypesFromSerializers
|
|
|
54
29
|
|
|
55
30
|
refine Class do
|
|
56
31
|
# Internal: Name of the TypeScript interface.
|
|
57
|
-
def
|
|
32
|
+
def ts_name
|
|
58
33
|
TypesFromSerializers.config.name_from_serializer.call(name).tr_s(":", "")
|
|
59
34
|
end
|
|
60
35
|
|
|
61
36
|
# Internal: The base name of the TypeScript file to be written.
|
|
62
|
-
def
|
|
37
|
+
def ts_filename
|
|
63
38
|
TypesFromSerializers.config.name_from_serializer.call(name).gsub("::", "/")
|
|
64
39
|
end
|
|
65
40
|
|
|
66
|
-
# Internal:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
types_from: _serializer_types_from,
|
|
71
|
-
attributes: _attributes.map { |key, options|
|
|
72
|
-
typed_attrs = _typed_attributes.fetch(key, {})
|
|
73
|
-
FieldMetadata.new(
|
|
74
|
-
**typed_attrs,
|
|
75
|
-
name: key,
|
|
76
|
-
optional: typed_attrs[:optional] || options.key?(:if),
|
|
77
|
-
)
|
|
78
|
-
},
|
|
79
|
-
associations: _associations.map { |key, options|
|
|
80
|
-
FieldMetadata.new(
|
|
81
|
-
name: options.fetch(:root, key),
|
|
82
|
-
type: options.fetch(:serializer),
|
|
83
|
-
optional: options.key?(:if),
|
|
84
|
-
many: options.fetch(:write_method) == :write_many,
|
|
85
|
-
)
|
|
86
|
-
},
|
|
87
|
-
)
|
|
41
|
+
# Internal: The columns corresponding to the serializer model, if it's a
|
|
42
|
+
# record.
|
|
43
|
+
def model_columns
|
|
44
|
+
@model_columns ||= _serializer_model_name&.to_model.try(:columns_hash) || {}
|
|
88
45
|
end
|
|
89
46
|
|
|
90
|
-
# Internal:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
47
|
+
# Internal: The TypeScript properties of the serialzeir interface.
|
|
48
|
+
def ts_properties
|
|
49
|
+
@ts_properties ||= begin
|
|
50
|
+
types_from = try(:_serializer_types_from)
|
|
51
|
+
|
|
52
|
+
prepare_attributes(
|
|
53
|
+
sort_by: TypesFromSerializers.config.sort_properties_by,
|
|
54
|
+
transform_keys: TypesFromSerializers.config.transform_keys || try(:_transform_keys) || DEFAULT_TRANSFORM_KEYS,
|
|
55
|
+
)
|
|
56
|
+
.flat_map { |key, options|
|
|
57
|
+
if options[:association] == :flat
|
|
58
|
+
options.fetch(:serializer).ts_properties
|
|
59
|
+
else
|
|
60
|
+
Property.new(
|
|
61
|
+
name: key,
|
|
62
|
+
type: options[:serializer] || options[:type],
|
|
63
|
+
optional: options[:optional] || options.key?(:if),
|
|
64
|
+
multi: options[:association] == :many,
|
|
65
|
+
column_name: options.fetch(:value_from),
|
|
66
|
+
).tap do |property|
|
|
67
|
+
property.infer_type_from(model_columns, types_from)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
}
|
|
103
71
|
end
|
|
104
72
|
end
|
|
105
73
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
74
|
+
# Internal: A first pass of gathering types for the serializer attributes.
|
|
75
|
+
def ts_interface
|
|
76
|
+
@ts_interface ||= Interface.new(
|
|
77
|
+
name: ts_name,
|
|
78
|
+
filename: ts_filename,
|
|
79
|
+
properties: ts_properties,
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Internal: The configuration for TypeScript generation.
|
|
86
|
+
Config = Struct.new(
|
|
87
|
+
:base_serializers,
|
|
88
|
+
:serializers_dirs,
|
|
89
|
+
:output_dir,
|
|
90
|
+
:custom_types_dir,
|
|
91
|
+
:name_from_serializer,
|
|
92
|
+
:global_types,
|
|
93
|
+
:sort_properties_by,
|
|
94
|
+
:sql_to_typescript_type_mapping,
|
|
95
|
+
:skip_serializer_if,
|
|
96
|
+
:transform_keys,
|
|
97
|
+
keyword_init: true,
|
|
98
|
+
) do
|
|
99
|
+
def relative_custom_types_dir
|
|
100
|
+
@relative_custom_types_dir ||= (custom_types_dir || output_dir.parent).relative_path_from(output_dir)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def unknown_type
|
|
104
|
+
sql_to_typescript_type_mapping.default
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Internal: Information to generate a TypeScript interface for a serializer.
|
|
109
|
+
Interface = Struct.new(
|
|
110
|
+
:name,
|
|
111
|
+
:filename,
|
|
112
|
+
:properties,
|
|
113
|
+
keyword_init: true,
|
|
114
|
+
) do
|
|
115
|
+
using SerializerRefinements
|
|
116
|
+
|
|
117
|
+
def inspect
|
|
118
|
+
to_h.inspect
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Internal: Returns a list of imports for types used in this interface.
|
|
122
|
+
def used_imports
|
|
123
|
+
association_serializers, attribute_types = properties.map(&:type).compact.uniq
|
|
124
|
+
.partition { |type| type.respond_to?(:ts_interface) }
|
|
125
|
+
|
|
126
|
+
serializer_type_imports = association_serializers.map(&:ts_interface)
|
|
127
|
+
.map { |type| [type.name, relative_path(type.pathname, pathname)] }
|
|
128
|
+
|
|
129
|
+
custom_type_imports = attribute_types
|
|
130
|
+
.flat_map { |type| extract_typescript_types(type.to_s) }
|
|
131
|
+
.uniq
|
|
132
|
+
.reject { |type| global_type?(type) }
|
|
133
|
+
.map { |type|
|
|
134
|
+
type_path = TypesFromSerializers.config.relative_custom_types_dir.join(type)
|
|
135
|
+
[type, relative_path(type_path, pathname)]
|
|
109
136
|
}
|
|
110
137
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
.reject { |type| typescript_native_type?(type) }
|
|
115
|
-
.map { |type|
|
|
116
|
-
[type, "~/types/#{type}"]
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
(assoc_imports + attr_imports).uniq.map { |interface, filename|
|
|
120
|
-
"import type #{interface} from '#{filename}'\n"
|
|
121
|
-
}.uniq
|
|
122
|
-
end
|
|
138
|
+
(custom_type_imports + serializer_type_imports)
|
|
139
|
+
.map { |interface, filename| "import type #{interface} from '#{filename}'\n" }
|
|
140
|
+
end
|
|
123
141
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
142
|
+
def as_typescript
|
|
143
|
+
<<~TS
|
|
144
|
+
interface #{name} {
|
|
145
|
+
#{properties.index_by(&:name).values.map(&:as_typescript).join("\n ")}
|
|
146
|
+
}
|
|
147
|
+
TS
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
protected
|
|
151
|
+
|
|
152
|
+
def pathname
|
|
153
|
+
@pathname ||= Pathname.new(filename)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Internal: Calculates a relative path that can be used in an import.
|
|
157
|
+
def relative_path(target_path, importer_path)
|
|
158
|
+
path = target_path.relative_path_from(importer_path.parent).to_s
|
|
159
|
+
path.start_with?(".") ? path : "./#{path}"
|
|
160
|
+
end
|
|
128
161
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
162
|
+
# Internal: Extracts any types inside generics or array types.
|
|
163
|
+
def extract_typescript_types(type)
|
|
164
|
+
type.split(/[<>\[\],\s|]+/)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# NOTE: Treat uppercase names as custom types.
|
|
168
|
+
# Lowercase names would be native types, such as :string and :boolean.
|
|
169
|
+
def global_type?(type)
|
|
170
|
+
type[0] == type[0].downcase || TypesFromSerializers.config.global_types.include?(type)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Internal: The type metadata for a serializer attribute.
|
|
175
|
+
Property = Struct.new(
|
|
176
|
+
:name,
|
|
177
|
+
:type,
|
|
178
|
+
:optional,
|
|
179
|
+
:multi,
|
|
180
|
+
:column_name,
|
|
181
|
+
keyword_init: true,
|
|
182
|
+
) do
|
|
183
|
+
using SerializerRefinements
|
|
184
|
+
|
|
185
|
+
def inspect
|
|
186
|
+
to_h.inspect
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Internal: Infers the property's type by checking a corresponding SQL
|
|
190
|
+
# column, or falling back to a TypeScript interface if provided.
|
|
191
|
+
def infer_type_from(columns_hash, ts_interface)
|
|
192
|
+
if type
|
|
193
|
+
type
|
|
194
|
+
elsif (column = columns_hash[column_name.to_s])
|
|
195
|
+
self.multi = true if column.try(:array)
|
|
196
|
+
self.optional = true if column.null && !column.default
|
|
197
|
+
self.type = TypesFromSerializers.config.sql_to_typescript_type_mapping[column.type]
|
|
198
|
+
elsif ts_interface
|
|
199
|
+
self.type = "#{ts_interface}['#{name}']"
|
|
133
200
|
end
|
|
201
|
+
end
|
|
134
202
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
203
|
+
def as_typescript
|
|
204
|
+
type_str = if type.respond_to?(:ts_name)
|
|
205
|
+
type.ts_name
|
|
206
|
+
else
|
|
207
|
+
type || TypesFromSerializers.config.unknown_type
|
|
141
208
|
end
|
|
209
|
+
|
|
210
|
+
"#{name}#{"?" if optional}: #{type_str}#{"[]" if multi}"
|
|
142
211
|
end
|
|
143
212
|
end
|
|
144
213
|
|
|
@@ -199,6 +268,7 @@ module TypesFromSerializers
|
|
|
199
268
|
# Public: Generates code for all serializers in the app.
|
|
200
269
|
def generate(force: ENV["SERIALIZER_TYPES_FORCE"])
|
|
201
270
|
@force_generation = force
|
|
271
|
+
config.output_dir.rmtree if force && config.output_dir.exist?
|
|
202
272
|
generate_index_file
|
|
203
273
|
|
|
204
274
|
loaded_serializers.each do |serializer|
|
|
@@ -217,12 +287,10 @@ module TypesFromSerializers
|
|
|
217
287
|
|
|
218
288
|
# Internal: Defines a TypeScript interface for the serializer.
|
|
219
289
|
def generate_interface_for(serializer)
|
|
220
|
-
|
|
221
|
-
filename = serializer.typescript_interface_basename
|
|
290
|
+
interface = serializer.ts_interface
|
|
222
291
|
|
|
223
|
-
write_if_changed(filename: filename, cache_key:
|
|
224
|
-
|
|
225
|
-
serializer_interface_content(serializer, metadata)
|
|
292
|
+
write_if_changed(filename: interface.filename, cache_key: interface.inspect) {
|
|
293
|
+
serializer_interface_content(interface)
|
|
226
294
|
}
|
|
227
295
|
end
|
|
228
296
|
|
|
@@ -236,8 +304,11 @@ module TypesFromSerializers
|
|
|
236
304
|
end
|
|
237
305
|
|
|
238
306
|
# Internal: Checks if it should avoid generating an interface.
|
|
239
|
-
def skip_serializer?(
|
|
240
|
-
|
|
307
|
+
def skip_serializer?(serializer)
|
|
308
|
+
serializer.name.in?(config.base_serializers) ||
|
|
309
|
+
config.skip_serializer_if.call(serializer) ||
|
|
310
|
+
# NOTE: Ignore inline serializers.
|
|
311
|
+
serializer.ts_name.include?("Serializer")
|
|
241
312
|
end
|
|
242
313
|
|
|
243
314
|
# Internal: Returns an object compatible with FileUpdateChecker.
|
|
@@ -268,7 +339,7 @@ module TypesFromSerializers
|
|
|
268
339
|
.flat_map(&:descendants)
|
|
269
340
|
.uniq
|
|
270
341
|
.sort_by(&:name)
|
|
271
|
-
.reject { |s| skip_serializer?(s
|
|
342
|
+
.reject { |s| skip_serializer?(s) }
|
|
272
343
|
rescue NameError
|
|
273
344
|
raise ArgumentError, "Please ensure all your serializers extend BaseSerializer, or configure `config.base_serializers`."
|
|
274
345
|
end
|
|
@@ -288,12 +359,18 @@ module TypesFromSerializers
|
|
|
288
359
|
name_from_serializer: ->(name) { name.delete_suffix("Serializer") },
|
|
289
360
|
|
|
290
361
|
# Types that don't need to be imported in TypeScript.
|
|
291
|
-
|
|
362
|
+
global_types: [
|
|
292
363
|
"Array",
|
|
293
364
|
"Record",
|
|
294
365
|
"Date",
|
|
295
366
|
].to_set,
|
|
296
367
|
|
|
368
|
+
# Allows to choose a different sort order, alphabetical by default.
|
|
369
|
+
sort_properties_by: :name,
|
|
370
|
+
|
|
371
|
+
# Allows to avoid generating a serializer.
|
|
372
|
+
skip_serializer_if: ->(serializer) { false },
|
|
373
|
+
|
|
297
374
|
# Maps SQL column types to TypeScript native and custom types.
|
|
298
375
|
sql_to_typescript_type_mapping: {
|
|
299
376
|
boolean: :boolean,
|
|
@@ -306,6 +383,9 @@ module TypesFromSerializers
|
|
|
306
383
|
}.tap do |types|
|
|
307
384
|
types.default = :unknown
|
|
308
385
|
end,
|
|
386
|
+
|
|
387
|
+
# Allows to transform keys, useful when converting objects client-side.
|
|
388
|
+
transform_keys: nil,
|
|
309
389
|
)
|
|
310
390
|
end
|
|
311
391
|
|
|
@@ -330,18 +410,18 @@ module TypesFromSerializers
|
|
|
330
410
|
<<~TS
|
|
331
411
|
//
|
|
332
412
|
// DO NOT MODIFY: This file was automatically generated by TypesFromSerializers.
|
|
333
|
-
#{serializers.map { |s|
|
|
413
|
+
#{serializers.map { |s|
|
|
414
|
+
"export type { default as #{s.ts_name} } from './#{s.ts_filename}'"
|
|
415
|
+
}.join("\n")}
|
|
334
416
|
TS
|
|
335
417
|
end
|
|
336
418
|
|
|
337
|
-
def serializer_interface_content(
|
|
419
|
+
def serializer_interface_content(interface)
|
|
338
420
|
<<~TS
|
|
339
421
|
//
|
|
340
422
|
// DO NOT MODIFY: This file was automatically generated by TypesFromSerializers.
|
|
341
|
-
#{
|
|
342
|
-
export default
|
|
343
|
-
#{serializer.typescript_fields(metadata).join("\n")}
|
|
344
|
-
}
|
|
423
|
+
#{interface.used_imports.join}
|
|
424
|
+
export default #{interface.as_typescript}
|
|
345
425
|
TS
|
|
346
426
|
end
|
|
347
427
|
|
|
@@ -36,8 +36,11 @@ class TypesFromSerializers::Railtie < Rails::Railtie
|
|
|
36
36
|
desc "Generates TypeScript interfaces for each serializer in the app."
|
|
37
37
|
task generate: :environment do
|
|
38
38
|
require_relative "generator"
|
|
39
|
+
start_time = Time.zone.now
|
|
40
|
+
print "Generating TypeScript interfaces..."
|
|
39
41
|
serializers = TypesFromSerializers.generate(force: true)
|
|
40
|
-
puts "
|
|
42
|
+
puts "completed in #{(Time.zone.now - start_time).round(2)} seconds.\n"
|
|
43
|
+
puts "Found #{serializers.size} serializers:"
|
|
41
44
|
puts serializers.map { |s| "\t#{s.name}" }.join("\n")
|
|
42
45
|
end
|
|
43
46
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: types_from_serializers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Máximo Mussini
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-04-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: railties
|
|
@@ -17,9 +17,6 @@ dependencies:
|
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '5.1'
|
|
20
|
-
- - "<"
|
|
21
|
-
- !ruby/object:Gem::Version
|
|
22
|
-
version: '8'
|
|
23
20
|
type: :runtime
|
|
24
21
|
prerelease: false
|
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -27,23 +24,26 @@ dependencies:
|
|
|
27
24
|
- - ">="
|
|
28
25
|
- !ruby/object:Gem::Version
|
|
29
26
|
version: '5.1'
|
|
30
|
-
- - "<"
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '8'
|
|
33
27
|
- !ruby/object:Gem::Dependency
|
|
34
28
|
name: oj_serializers
|
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
|
36
30
|
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 2.0.2
|
|
37
34
|
- - "~>"
|
|
38
35
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
36
|
+
version: '2.0'
|
|
40
37
|
type: :runtime
|
|
41
38
|
prerelease: false
|
|
42
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
40
|
requirements:
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: 2.0.2
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
46
|
+
version: '2.0'
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: listen
|
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|