typelizer 0.5.4 → 0.5.6
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 +44 -1
- data/README.md +7 -0
- data/lib/typelizer/config.rb +2 -0
- data/lib/typelizer/interface.rb +3 -3
- data/lib/typelizer/model_plugins/active_record.rb +21 -0
- data/lib/typelizer/property_sorter.rb +24 -0
- data/lib/typelizer/serializer_plugins/alba/trait_attribute_collector.rb +9 -5
- data/lib/typelizer/serializer_plugins/alba/trait_interface.rb +2 -1
- data/lib/typelizer/version.rb +1 -1
- data/lib/typelizer.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f1c1d02eab4c7f1ea170ecd4b855fa37952273faa3223333cd6f6f2020dad397
|
|
4
|
+
data.tar.gz: 519c348552314735af8c1ba5072a8cd7cbb492b822d0bf5564b95b965f42ff12
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e5d72c98f8ac58bba2a48673ec3f54e86e6aba2d25168312433d5288461aef7c1fd5d0d65aa2137759f03831c432aee5d9a2f5fc626068d302d295749d1f9ca7
|
|
7
|
+
data.tar.gz: 4134b806f9f788a32920dfb6ae8980b66083c7b22b897be3f3d005915fd5e444712fe12535a409c47c6d5cee4158f91696c11df7692f2ced26361bc169cd91d3
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,47 @@ and this project adheres to [Semantic Versioning].
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.6] - 2026-01-12
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Type inference for serialized fields. `serialize :skills, type: Array` generates `Array<unknown>`, `serialize :settings, type: Hash` generates `Record<string, unknown>`. ([@skryukov])
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Alba: respect `key:` option for associations defined in traits. ([@skryukov])
|
|
19
|
+
|
|
20
|
+
## [0.5.5] - 2025-12-24
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- New `properties_sort_order` configuration option for consistent property ordering in generated TypeScript interfaces. ([@skryukov])
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
Typelizer.configure do |config|
|
|
28
|
+
# Sort properties alphabetically with 'id' first
|
|
29
|
+
config.properties_sort_order = :id_first_alphabetical
|
|
30
|
+
end
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Available options:
|
|
34
|
+
- `:none` (default) - preserve serializer definition order
|
|
35
|
+
- `:alphabetical` - sort properties A-Z (case-insensitive)
|
|
36
|
+
- `:id_first_alphabetical` - place `id` first, then sort remaining A-Z
|
|
37
|
+
- `Proc` - custom sorting logic
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
# Custom sorting example
|
|
41
|
+
config.properties_sort_order = ->(props) {
|
|
42
|
+
priority = %w[id uuid type]
|
|
43
|
+
props.sort_by { |p| [priority.index(p.name) || 999, p.name] }
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- Fix self-import issue when using custom `typelize` types for self-referential associations in namespaced serializers. ([@skryukov])
|
|
50
|
+
|
|
10
51
|
## [0.5.4] - 2025-12-08
|
|
11
52
|
|
|
12
53
|
### Added
|
|
@@ -279,7 +320,9 @@ and this project adheres to [Semantic Versioning].
|
|
|
279
320
|
[@prog-supdex]: https://github.com/prog-supdex
|
|
280
321
|
[@ventsislaf]: https://github.com/ventsislaf
|
|
281
322
|
|
|
282
|
-
[Unreleased]: https://github.com/skryukov/typelizer/compare/v0.5.
|
|
323
|
+
[Unreleased]: https://github.com/skryukov/typelizer/compare/v0.5.6...HEAD
|
|
324
|
+
[0.5.6]: https://github.com/skryukov/typelizer/compare/v0.5.5...v0.5.6
|
|
325
|
+
[0.5.5]: https://github.com/skryukov/typelizer/compare/v0.5.4...v0.5.5
|
|
283
326
|
[0.5.4]: https://github.com/skryukov/typelizer/compare/v0.5.3...v0.5.4
|
|
284
327
|
[0.5.3]: https://github.com/skryukov/typelizer/compare/v0.5.2...v0.5.3
|
|
285
328
|
[0.5.2]: https://github.com/skryukov/typelizer/compare/v0.5.1...v0.5.2
|
data/README.md
CHANGED
|
@@ -486,6 +486,13 @@ Typelizer.configure do |config|
|
|
|
486
486
|
# Custom transformation for generated properties
|
|
487
487
|
config.properties_transformer = ->(properties) { ... }
|
|
488
488
|
|
|
489
|
+
# Strategy for ordering properties in generated TypeScript interfaces
|
|
490
|
+
# :none - preserve serializer definition order (default)
|
|
491
|
+
# :alphabetical - sort properties A-Z (case-insensitive)
|
|
492
|
+
# :id_first_alphabetical - place 'id' first, then sort remaining A-Z
|
|
493
|
+
# Proc - custom sorting function receiving array of Property objects
|
|
494
|
+
config.properties_sort_order = :none
|
|
495
|
+
|
|
489
496
|
# Plugin for model type inference (default: ModelPlugins::Auto)
|
|
490
497
|
config.model_plugin = Typelizer::ModelPlugins::Auto
|
|
491
498
|
|
data/lib/typelizer/config.rb
CHANGED
|
@@ -23,6 +23,7 @@ module Typelizer
|
|
|
23
23
|
:serializer_name_mapper,
|
|
24
24
|
:serializer_model_mapper,
|
|
25
25
|
:properties_transformer,
|
|
26
|
+
:properties_sort_order,
|
|
26
27
|
:model_plugin,
|
|
27
28
|
:serializer_plugin,
|
|
28
29
|
:plugin_configs,
|
|
@@ -77,6 +78,7 @@ module Typelizer
|
|
|
77
78
|
types_import_path: "@/types",
|
|
78
79
|
types_global: DEFAULT_TYPES_GLOBAL,
|
|
79
80
|
properties_transformer: nil,
|
|
81
|
+
properties_sort_order: :none,
|
|
80
82
|
verbatim_module_syntax: false
|
|
81
83
|
}
|
|
82
84
|
end
|
data/lib/typelizer/interface.rb
CHANGED
|
@@ -48,7 +48,7 @@ module Typelizer
|
|
|
48
48
|
props = serializer_plugin.meta_fields || []
|
|
49
49
|
props = infer_types(props, :_typelizer_meta_attributes)
|
|
50
50
|
props = config.properties_transformer.call(props) if config.properties_transformer
|
|
51
|
-
props
|
|
51
|
+
PropertySorter.sort(props, config.properties_sort_order)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
@@ -63,7 +63,7 @@ module Typelizer
|
|
|
63
63
|
props = serializer_plugin.properties
|
|
64
64
|
props = infer_types(props)
|
|
65
65
|
props = config.properties_transformer.call(props) if config.properties_transformer
|
|
66
|
-
props
|
|
66
|
+
PropertySorter.sort(props, config.properties_sort_order)
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
@@ -119,7 +119,7 @@ module Typelizer
|
|
|
119
119
|
prop.with_traits.map { |t| "#{prop.type.name}#{t.to_s.camelize}Trait" }
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
-
(custom_type_imports + serializer_types + trait_imports + Array(parent_interface&.name)).uniq -
|
|
122
|
+
(custom_type_imports + serializer_types + trait_imports + Array(parent_interface&.name)).uniq - [self_type_name, name]
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
125
|
|
|
@@ -104,6 +104,10 @@ module Typelizer
|
|
|
104
104
|
attribute_type_obj = model_class.attribute_types.fetch(prop.column_name.to_s, nil)
|
|
105
105
|
return nil unless attribute_type_obj
|
|
106
106
|
|
|
107
|
+
if attribute_type_obj.instance_of?(::ActiveRecord::Type::Serialized)
|
|
108
|
+
return infer_types_for_serialized(prop, attribute_type_obj)
|
|
109
|
+
end
|
|
110
|
+
|
|
107
111
|
if attribute_type_obj.respond_to?(:subtype)
|
|
108
112
|
prop.type = @config.type_mapping[attribute_type_obj.subtype.type]
|
|
109
113
|
prop.multi = true
|
|
@@ -113,6 +117,23 @@ module Typelizer
|
|
|
113
117
|
|
|
114
118
|
prop
|
|
115
119
|
end
|
|
120
|
+
|
|
121
|
+
def infer_types_for_serialized(prop, type_obj)
|
|
122
|
+
object_class = type_obj.coder.try(:object_class) ||
|
|
123
|
+
type_obj.try(:object_class)
|
|
124
|
+
|
|
125
|
+
case object_class&.to_s
|
|
126
|
+
when "Array"
|
|
127
|
+
prop.type = :unknown
|
|
128
|
+
prop.multi = true
|
|
129
|
+
when "Hash"
|
|
130
|
+
prop.type = "Record<string, unknown>"
|
|
131
|
+
else
|
|
132
|
+
prop.type = :unknown
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
prop
|
|
136
|
+
end
|
|
116
137
|
end
|
|
117
138
|
end
|
|
118
139
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Typelizer
|
|
4
|
+
module PropertySorter
|
|
5
|
+
def self.sort(props, sort_order)
|
|
6
|
+
case sort_order
|
|
7
|
+
when :none, nil
|
|
8
|
+
props
|
|
9
|
+
when :alphabetical
|
|
10
|
+
props.sort_by { |p| p.name.to_s.downcase }
|
|
11
|
+
when :id_first_alphabetical
|
|
12
|
+
props.sort_by { |p| [(p.name.to_s.downcase == "id") ? 0 : 1, p.name.to_s.downcase] }
|
|
13
|
+
when Proc
|
|
14
|
+
result = sort_order.call(props)
|
|
15
|
+
result.is_a?(Array) ? result : props
|
|
16
|
+
else
|
|
17
|
+
props
|
|
18
|
+
end
|
|
19
|
+
rescue => e
|
|
20
|
+
Typelizer.logger.warn("PropertySorter error: #{e.message}, preserving original order")
|
|
21
|
+
props
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -54,17 +54,19 @@ module Typelizer
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# Simple struct to hold association info from traits
|
|
57
|
-
TraitAssociation = Struct.new(:name, :resource, :with_traits, :multi, keyword_init: true)
|
|
57
|
+
TraitAssociation = Struct.new(:name, :resource, :with_traits, :multi, :key, keyword_init: true)
|
|
58
58
|
|
|
59
59
|
# Support association methods that might be used in traits
|
|
60
60
|
def one(name, **options, &block)
|
|
61
61
|
resource = options[:resource] || options[:serializer]
|
|
62
62
|
with_traits = options[:with_traits]
|
|
63
|
-
|
|
63
|
+
key = options[:key] || name
|
|
64
|
+
@collected_attributes[key] = TraitAssociation.new(
|
|
64
65
|
name: name,
|
|
65
66
|
resource: resource,
|
|
66
67
|
with_traits: with_traits,
|
|
67
|
-
multi: false
|
|
68
|
+
multi: false,
|
|
69
|
+
key: key
|
|
68
70
|
)
|
|
69
71
|
end
|
|
70
72
|
|
|
@@ -74,11 +76,13 @@ module Typelizer
|
|
|
74
76
|
def many(name, **options, &block)
|
|
75
77
|
resource = options[:resource] || options[:serializer]
|
|
76
78
|
with_traits = options[:with_traits]
|
|
77
|
-
|
|
79
|
+
key = options[:key] || name
|
|
80
|
+
@collected_attributes[key] = TraitAssociation.new(
|
|
78
81
|
name: name,
|
|
79
82
|
resource: resource,
|
|
80
83
|
with_traits: with_traits,
|
|
81
|
-
multi: true
|
|
84
|
+
multi: true,
|
|
85
|
+
key: key
|
|
82
86
|
)
|
|
83
87
|
end
|
|
84
88
|
|
|
@@ -24,7 +24,8 @@ module Typelizer
|
|
|
24
24
|
def properties
|
|
25
25
|
@properties ||= begin
|
|
26
26
|
props, typelizes = plugin.trait_properties(trait_name)
|
|
27
|
-
infer_types(props, typelizes)
|
|
27
|
+
props = infer_types(props, typelizes)
|
|
28
|
+
PropertySorter.sort(props, config.properties_sort_order)
|
|
28
29
|
end
|
|
29
30
|
end
|
|
30
31
|
|
data/lib/typelizer/version.rb
CHANGED
data/lib/typelizer.rb
CHANGED
|
@@ -11,6 +11,7 @@ require_relative "typelizer/serializer_config_layer"
|
|
|
11
11
|
|
|
12
12
|
require_relative "typelizer/contexts/writer_context"
|
|
13
13
|
require_relative "typelizer/contexts/scan_context"
|
|
14
|
+
require_relative "typelizer/property_sorter"
|
|
14
15
|
require_relative "typelizer/interface"
|
|
15
16
|
require_relative "typelizer/renderer"
|
|
16
17
|
require_relative "typelizer/writer"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: typelizer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Svyatoslav Kryukov
|
|
@@ -60,6 +60,7 @@ files:
|
|
|
60
60
|
- lib/typelizer/model_plugins/auto.rb
|
|
61
61
|
- lib/typelizer/model_plugins/poro.rb
|
|
62
62
|
- lib/typelizer/property.rb
|
|
63
|
+
- lib/typelizer/property_sorter.rb
|
|
63
64
|
- lib/typelizer/railtie.rb
|
|
64
65
|
- lib/typelizer/renderer.rb
|
|
65
66
|
- lib/typelizer/serializer_config_layer.rb
|
|
@@ -104,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
104
105
|
- !ruby/object:Gem::Version
|
|
105
106
|
version: '0'
|
|
106
107
|
requirements: []
|
|
107
|
-
rubygems_version:
|
|
108
|
+
rubygems_version: 3.6.9
|
|
108
109
|
specification_version: 4
|
|
109
110
|
summary: A TypeScript type generator for Ruby serializers.
|
|
110
111
|
test_files: []
|