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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0528e1e626a19920401677115cc49d13d3c2a730b8f332e285dcdaada8699a62'
4
- data.tar.gz: 171dde8c90cc46ee6eb5cf434f2c7cd83f15098a233e9e2a5dbb2b5f36ba470c
3
+ metadata.gz: f1c1d02eab4c7f1ea170ecd4b855fa37952273faa3223333cd6f6f2020dad397
4
+ data.tar.gz: 519c348552314735af8c1ba5072a8cd7cbb492b822d0bf5564b95b965f42ff12
5
5
  SHA512:
6
- metadata.gz: b3785036afe6f23d5f5f830271081d20f99810e3582d853b28bd34e5558e20609615b929a870c6ef518b75389b48c6e092a8043d8c24510ad1a01b9d82449021
7
- data.tar.gz: c0bde62a2756d3b67cba8bf8fa061f898d2837bae191f80fa6960c1fe08c654044807c0c8157cffa6c45edee632716f7c105a54cae4b5f87d3ece6b546c7cda1
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.4...HEAD
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
 
@@ -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
@@ -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 - Array(self_type_name)
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
- @collected_attributes[name] = TraitAssociation.new(
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
- @collected_attributes[name] = TraitAssociation.new(
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Typelizer
4
- VERSION = "0.5.4"
4
+ VERSION = "0.5.6"
5
5
  end
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
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: 4.0.0
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: []