typespec_from_serializers 0.5.4 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e442eede2713d04dc58848c414f8c97fb3131ec16aff96c33b31fc2b9bfe248b
4
- data.tar.gz: 88424e945a35538e356adceaf9abdcb2ceb5997469a94efe9d661c31b228050a
3
+ metadata.gz: 80df92c4cd5814bc352130e1d4eb56d648c7efbb46158a99bf98a100f55cc186
4
+ data.tar.gz: f1d3027b282117a49be85a929cf85183ce22a08e39a6a8390d7f3be1363c85cb
5
5
  SHA512:
6
- metadata.gz: 960f08588e534643e0ecdb2cf4f3129d351995330f4474748c10ee8f7e844e202614c3e8ae391753c5b45b555831398aff2ffa3474af080ef9e5767b86f2f706
7
- data.tar.gz: 32cd0ff2d5b1e339829a78f7150b3870a4ef954d61d12c8738b3ebe5f0d04b31ea7ba1988fc4efd7f5c46e436f56e96d52b2719f77b29a95231fdfaf13d07777
6
+ metadata.gz: 99f22f4f43af8b642d4e69e81b089f472e252b9075df4975a34e392226fea6c5b9e01b39bd8cb555a3f03c1bac0cb8b113a04ea2daa68e0ea87a4b40c6f0a5d7
7
+ data.tar.gz: 38fc2e2f89bc1e8933de619f8573806bb562e907fc71a46c66c58d4411f25299c6f96d6507440542c8b1ebe841bfe3d2538c1eaa2a0ceaea9c556a1edeb771ef
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # TypeSpec From Serializers Changelog
2
2
 
3
+ ## [0.6.0] - 2026-03-03
4
+
5
+ ### Added
6
+ - Automatic route namespace/interface disambiguation: names that collide with model names are suffixed (e.g., `namespace Task` → `namespace TaskRoutes` when `TaskSerializer` exists)
7
+ - New `route_namespace_suffix` config option (default: `"Routes"`) to control the disambiguation suffix
8
+ - Content-based cache keys: files are only rewritten when generated output actually changes, eliminating unnecessary diffs from internal representation changes
9
+
3
10
  ## [0.5.4] - 2025-12-23
4
11
 
5
12
  ### Fixed
@@ -213,6 +213,7 @@ module TypeSpecFromSerializers
213
213
  :custom_typespec_dir,
214
214
  :name_from_serializer,
215
215
  :controller_suffix,
216
+ :route_namespace_suffix,
216
217
  :param_method_suffix,
217
218
  :global_types,
218
219
  :sort_properties_by,
@@ -653,9 +654,10 @@ module TypeSpecFromSerializers
653
654
  # Internal: Defines a TypeSpec model for the serializer.
654
655
  def generate_model_for(serializer)
655
656
  model = serializer.tsp_model
657
+ content = serializer_model_content(model)
656
658
 
657
- write_if_changed(filename: "models/#{model.filename}", cache_key: model.inspect, extension: "tsp") {
658
- serializer_model_content(model)
659
+ write_if_changed(filename: "models/#{model.filename}", cache_key: content, extension: "tsp") {
660
+ content
659
661
  }
660
662
  rescue => e
661
663
  $stderr.puts "ERROR in generate_model_for(#{serializer.name}): #{e.class}: #{e.message}"
@@ -665,10 +667,10 @@ module TypeSpecFromSerializers
665
667
 
666
668
  # Internal: Allows to import all serializer types from a single file.
667
669
  def generate_index_file
668
- cache_key = all_serializer_files.map { |file| file.delete_prefix(root.to_s) }.join
669
- write_if_changed(filename: "index", cache_key: cache_key) {
670
- load_serializers(all_serializer_files)
671
- serializers_index_content(loaded_serializers)
670
+ load_serializers(all_serializer_files)
671
+ content = serializers_index_content(loaded_serializers)
672
+ write_if_changed(filename: "index", cache_key: content) {
673
+ content
672
674
  }
673
675
  end
674
676
 
@@ -677,9 +679,9 @@ module TypeSpecFromSerializers
677
679
  return [] unless defined?(Rails) && Rails.application
678
680
 
679
681
  routes, controllers = collect_rails_routes
680
- cache_key = routes.map(&:inspect).join
681
- write_if_changed(filename: "routes", cache_key: cache_key) {
682
- routes_content(routes)
682
+ content = routes_content(routes)
683
+ write_if_changed(filename: "routes", cache_key: content) {
684
+ content
683
685
  }
684
686
 
685
687
  # Return list of controller class names
@@ -811,8 +813,10 @@ module TypeSpecFromSerializers
811
813
  operations = ns_routes.map { |route| build_operation(controller, route) }
812
814
  operations = make_operation_names_unique(operations)
813
815
 
816
+ interface_name = disambiguate_route_name(controller.tr("/", "_").camelize)
817
+
814
818
  Resource.new(
815
- name: controller.tr("/", "_").camelize,
819
+ name: interface_name,
816
820
  path: base_path.start_with?("/") ? base_path : "/#{base_path}",
817
821
  operations: operations,
818
822
  parent_namespace: parent_namespace,
@@ -915,11 +919,21 @@ module TypeSpecFromSerializers
915
919
  end
916
920
 
917
921
  # Internal: Extracts parent namespace from nested route paths
918
- # E.g., "/lands/{land_id}/comments" → "Land"
919
- # "/tasks/{task_id}/comments" → "Task"
922
+ # E.g., "/lands/{land_id}/comments" → "LandRoutes" (suffixed to avoid model collision)
923
+ # "/tasks/{task_id}/comments" → "TaskRoutes"
920
924
  def extract_parent_namespace(path)
921
925
  # Match pattern like /resource/:resource_id/nested (Rails uses : notation)
922
- path[%r{^/([^/]+)/:[^/]+_id/}, 1]&.singularize&.camelize
926
+ name = path[%r{^/([^/]+)/:[^/]+_id/}, 1]&.singularize&.camelize
927
+ return unless name
928
+
929
+ disambiguate_route_name(name)
930
+ end
931
+
932
+ # Internal: Suffixes a route namespace/interface name if it collides with a model name.
933
+ # E.g., "Task" → "TaskRoutes" when TaskSerializer exists.
934
+ def disambiguate_route_name(name)
935
+ model_names = loaded_serializers.map { |s| s.tsp_name }
936
+ model_names.include?(name) ? "#{name}#{config.route_namespace_suffix}" : name
923
937
  end
924
938
 
925
939
  # Internal: Simplifies operation name using REST conventions
@@ -1368,6 +1382,9 @@ module TypeSpecFromSerializers
1368
1382
  # Controller suffix for route generation reporting
1369
1383
  controller_suffix: "Controller",
1370
1384
 
1385
+ # Suffix for route namespaces/interfaces that collide with model names
1386
+ route_namespace_suffix: "Routes",
1387
+
1371
1388
  # Types that don't need to be imported in TypeSpec.
1372
1389
  global_types: [
1373
1390
  "Array",
@@ -2,5 +2,5 @@
2
2
 
3
3
  module TypeSpecFromSerializers
4
4
  # Public: This library adheres to semantic versioning.
5
- VERSION = "0.5.4"
5
+ VERSION = "0.6.0"
6
6
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typespec_from_serializers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danila Poyarkov
8
8
  - Máximo Mussini
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2025-12-23 00:00:00.000000000 Z
11
+ date: 2026-03-03 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: railties
@@ -328,7 +327,6 @@ homepage: https://github.com/dannote/typespec_from_serializers
328
327
  licenses:
329
328
  - MIT
330
329
  metadata: {}
331
- post_install_message:
332
330
  rdoc_options: []
333
331
  require_paths:
334
332
  - lib
@@ -343,8 +341,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
343
341
  - !ruby/object:Gem::Version
344
342
  version: '0'
345
343
  requirements: []
346
- rubygems_version: 3.5.16
347
- signing_key:
344
+ rubygems_version: 3.6.2
348
345
  specification_version: 4
349
346
  summary: Generate TypeSpec descriptions from your JSON serializers.
350
347
  test_files: []