typespec_from_serializers 0.5.3 → 0.5.4
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 +6 -0
- data/lib/typespec_from_serializers/generator.rb +46 -21
- data/lib/typespec_from_serializers/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e442eede2713d04dc58848c414f8c97fb3131ec16aff96c33b31fc2b9bfe248b
|
|
4
|
+
data.tar.gz: 88424e945a35538e356adceaf9abdcb2ceb5997469a94efe9d661c31b228050a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 960f08588e534643e0ecdb2cf4f3129d351995330f4474748c10ee8f7e844e202614c3e8ae391753c5b45b555831398aff2ffa3474af080ef9e5767b86f2f706
|
|
7
|
+
data.tar.gz: 32cd0ff2d5b1e339829a78f7150b3870a4ef954d61d12c8738b3ebe5f0d04b31ea7ba1988fc4efd7f5c46e436f56e96d52b2719f77b29a95231fdfaf13d07777
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# TypeSpec From Serializers Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.4] - 2025-12-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Transitive params extraction now follows method calls through intermediate methods
|
|
7
|
+
- Route-level `type:` declarations now only apply to actual path params (not inherited by collection routes)
|
|
8
|
+
|
|
3
9
|
## [0.5.3] - 2025-12-23
|
|
4
10
|
|
|
5
11
|
### Fixed
|
|
@@ -847,7 +847,10 @@ module TypeSpecFromSerializers
|
|
|
847
847
|
|
|
848
848
|
# Internal: Extracts all parameter types from route metadata and controller DSL
|
|
849
849
|
def extract_all_param_types(controller, route)
|
|
850
|
+
# Route-level types are for path params only - filter to actual path params
|
|
851
|
+
path_param_names = route[:path].scan(/:([a-zA-Z_][a-zA-Z0-9_]*)/).flatten
|
|
850
852
|
route_param_types = route[:param_types]
|
|
853
|
+
.select { |k, _| path_param_names.include?(k.to_s) }
|
|
851
854
|
.transform_keys(&:to_s)
|
|
852
855
|
.transform_values { |v| map_type_class_to_typespec(v) }
|
|
853
856
|
|
|
@@ -1133,19 +1136,40 @@ module TypeSpecFromSerializers
|
|
|
1133
1136
|
{}
|
|
1134
1137
|
end
|
|
1135
1138
|
|
|
1136
|
-
# Internal: Finds *_params methods that are called by a specific action method
|
|
1139
|
+
# Internal: Finds *_params methods that are called by a specific action method (transitively)
|
|
1137
1140
|
def find_params_methods_called_by_action(controller_class, action)
|
|
1138
1141
|
method_node = find_action_node(controller_class, action)
|
|
1139
1142
|
return [] unless method_node
|
|
1140
1143
|
|
|
1144
|
+
method = controller_class.instance_method(action)
|
|
1145
|
+
file_path, = method.source_location
|
|
1141
1146
|
suffix = config.param_method_suffix
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
.map(&:to_sym)
|
|
1147
|
+
|
|
1148
|
+
find_params_methods_transitively(file_path, method_node, suffix)
|
|
1145
1149
|
rescue
|
|
1146
1150
|
[]
|
|
1147
1151
|
end
|
|
1148
1152
|
|
|
1153
|
+
# Internal: Recursively finds *_params methods through intermediate method calls
|
|
1154
|
+
def find_params_methods_transitively(file_path, node, suffix, visited = Set.new)
|
|
1155
|
+
calls = find_method_calls(node)
|
|
1156
|
+
params_methods = calls.select { |name| name.end_with?(suffix) }.map(&:to_sym)
|
|
1157
|
+
|
|
1158
|
+
# Follow non-params method calls defined in the same file
|
|
1159
|
+
calls.each do |call_name|
|
|
1160
|
+
next if call_name.end_with?(suffix)
|
|
1161
|
+
next if visited.include?(call_name)
|
|
1162
|
+
|
|
1163
|
+
visited << call_name
|
|
1164
|
+
called_node = find_def_node(file_path) { |n| n.name.to_s == call_name }
|
|
1165
|
+
next unless called_node
|
|
1166
|
+
|
|
1167
|
+
params_methods.concat(find_params_methods_transitively(file_path, called_node, suffix, visited))
|
|
1168
|
+
end
|
|
1169
|
+
|
|
1170
|
+
params_methods.uniq
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1149
1173
|
# Internal: Finds the AST node for a controller action method.
|
|
1150
1174
|
def find_action_node(controller_class, action)
|
|
1151
1175
|
return unless controller_class.method_defined?(action)
|
|
@@ -1154,7 +1178,7 @@ module TypeSpecFromSerializers
|
|
|
1154
1178
|
file_path, line_number = method.source_location
|
|
1155
1179
|
return unless file_path && File.exist?(file_path)
|
|
1156
1180
|
|
|
1157
|
-
|
|
1181
|
+
find_def_node(file_path) { |node| node.location.start_line == line_number }
|
|
1158
1182
|
end
|
|
1159
1183
|
|
|
1160
1184
|
# Internal: Parses a Ruby file and caches the result.
|
|
@@ -1166,28 +1190,29 @@ module TypeSpecFromSerializers
|
|
|
1166
1190
|
end
|
|
1167
1191
|
end
|
|
1168
1192
|
|
|
1169
|
-
# Internal:
|
|
1170
|
-
def
|
|
1193
|
+
# Internal: Traverses all descendant nodes in BFS order.
|
|
1194
|
+
def each_descendant(node)
|
|
1195
|
+
return enum_for(:each_descendant, node) unless block_given?
|
|
1196
|
+
queue = [node]
|
|
1197
|
+
while (current = queue.shift)
|
|
1198
|
+
yield current
|
|
1199
|
+
queue.concat(current.compact_child_nodes)
|
|
1200
|
+
end
|
|
1201
|
+
end
|
|
1202
|
+
|
|
1203
|
+
# Internal: Finds a DefNode matching the given condition.
|
|
1204
|
+
def find_def_node(file_path)
|
|
1171
1205
|
ast = parse_file_cached(file_path)
|
|
1172
1206
|
return unless ast
|
|
1173
|
-
|
|
1174
|
-
queue = [ast]
|
|
1175
|
-
while (node = queue.shift)
|
|
1176
|
-
return node if node.is_a?(Prism::DefNode) && node.location.start_line == line_number
|
|
1177
|
-
queue.concat(node.compact_child_nodes)
|
|
1178
|
-
end
|
|
1179
|
-
nil
|
|
1207
|
+
each_descendant(ast).find { |node| node.is_a?(Prism::DefNode) && yield(node) }
|
|
1180
1208
|
end
|
|
1181
1209
|
|
|
1182
1210
|
# Internal: Finds all unqualified method call names in an AST node.
|
|
1183
1211
|
def find_method_calls(node)
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
queue.concat(current.compact_child_nodes)
|
|
1189
|
-
end
|
|
1190
|
-
calls.uniq
|
|
1212
|
+
each_descendant(node)
|
|
1213
|
+
.select { |n| n.is_a?(Prism::CallNode) && n.receiver.nil? }
|
|
1214
|
+
.map { |n| n.name.to_s }
|
|
1215
|
+
.uniq
|
|
1191
1216
|
end
|
|
1192
1217
|
|
|
1193
1218
|
# Internal: Extracts key-value types from Sorbet hash type
|