Module: TypeSpecFromSerializers
- Defined in:
- lib/typespec_from_serializers/generator.rb,
lib/typespec_from_serializers/rbi.rb,
lib/typespec_from_serializers/rdoc.rb,
lib/typespec_from_serializers/sorbet.rb,
lib/typespec_from_serializers/version.rb,
lib/typespec_from_serializers/dsl/routing.rb,
lib/typespec_from_serializers/dsl/controller.rb,
lib/typespec_from_serializers/dsl/serializer.rb,
lib/typespec_from_serializers/openapi_compiler.rb
Overview
Internal: A DSL to specify types for serializer attributes.
Defined Under Namespace
Modules: DSL, IO, Linting, MapperPatch, OpenAPICompiler, RBI, RDoc, ResourcesPatch, RoutePatch, RoutingPatchHelpers, SerializerRefinements, Sorbet Classes: Changes, Config, Interface, Operation, Property, Railtie, Resource, Runner, SerializerVisitor
Constant Summary collapse
- VERSION =
Public: This library adheres to semantic versioning.
"0.5.4"- DEFAULT_TRANSFORM_KEYS =
->(key) { key.camelize(:lower).chomp("?") }
- TYPESPEC_LANGUAGE_KEYWORDS =
TypeSpec language keywords that are always problematic
%w[ using extends is import model scalar enum union interface namespace op alias true false null ].to_set.freeze
- TYPESPEC_REFLECTION_TYPES =
TypeSpec Reflection types that conflict only at global scope When using a namespace, these names are safe (e.g., MyAPI.Model is OK)
%w[ Model Scalar Enum Union Interface Operation Namespace ].to_set.freeze
- REST_ACTIONS =
Rails RESTful resource action names
%w[index show create update destroy].freeze
- MEMBER_ACTIONS =
%w[show update destroy].freeze
- SPECIAL_ACTIONS =
%w[new edit].freeze
Class Attribute Summary collapse
-
.force_generation ⇒ Object
readonly
Returns the value of attribute force_generation.
Class Method Summary collapse
-
.config ⇒ Object
Public: Configuration of the code generator.
-
.generate(force: ) ⇒ Object
Public: Generates code for all serializers in the app.
- .generate_changed ⇒ Object
-
.generate_index_file ⇒ Object
Internal: Allows to import all serializer types from a single file.
-
.generate_model_for(serializer) ⇒ Object
Internal: Defines a TypeSpec model for the serializer.
-
.generate_routes ⇒ Object
Internal: Generates TypeSpec routes from Rails routes.
-
.loaded_serializers ⇒ Object
Public: Returns all loaded serializer classes.
-
.rbi_dir ⇒ Object
Public: Returns the RBI base directory path.
-
.root ⇒ Object
Public: Returns the application root path.
-
.serializers ⇒ Object
Public: Returns all loaded serializers.
-
.skip_serializer?(serializer) ⇒ Boolean
Internal: Checks if it should avoid generating an model.
-
.track_changes ⇒ Object
Internal: Returns an object compatible with FileUpdateChecker.
Class Attribute Details
.force_generation ⇒ Object (readonly)
Returns the value of attribute force_generation.
610 611 612 |
# File 'lib/typespec_from_serializers/generator.rb', line 610 def force_generation @force_generation end |
Class Method Details
.config ⇒ Object
Public: Configuration of the code generator.
613 614 615 616 617 |
# File 'lib/typespec_from_serializers/generator.rb', line 613 def config (@config ||= default_config(root)).tap do |config| yield(config) if block_given? end end |
.generate(force: ) ⇒ Object
Public: Generates code for all serializers in the app.
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
# File 'lib/typespec_from_serializers/generator.rb', line 620 def generate(force: ENV["SERIALIZER_TYPESPEC_FORCE"]) Linting.reset_count @force_generation = force clean_output_dir if force && config.output_dir.exist? if config.namespace load_serializers(all_serializer_files) if force else generate_index_file end controllers = generate_routes serializers = loaded_serializers serializers.each do |serializer| generate_model_for(serializer) end Linting.print_summary {serializers: serializers, controllers: controllers} end |
.generate_changed ⇒ Object
644 645 646 647 648 649 650 651 |
# File 'lib/typespec_from_serializers/generator.rb', line 644 def generate_changed if changes.updated? config.output_dir.rmtree if changes.any_removed? load_serializers(changes.modified_files) generate changes.clear end end |
.generate_index_file ⇒ Object
Internal: Allows to import all serializer types from a single file.
667 668 669 670 671 672 673 |
# File 'lib/typespec_from_serializers/generator.rb', line 667 def generate_index_file cache_key = all_serializer_files.map { |file| file.delete_prefix(root.to_s) }.join write_if_changed(filename: "index", cache_key: cache_key) { load_serializers(all_serializer_files) serializers_index_content(loaded_serializers) } end |
.generate_model_for(serializer) ⇒ Object
Internal: Defines a TypeSpec model for the serializer.
654 655 656 657 658 659 660 661 662 663 664 |
# File 'lib/typespec_from_serializers/generator.rb', line 654 def generate_model_for(serializer) model = serializer.tsp_model write_if_changed(filename: "models/#{model.filename}", cache_key: model.inspect, extension: "tsp") { serializer_model_content(model) } rescue => e $stderr.puts "ERROR in generate_model_for(#{serializer.name}): #{e.class}: #{e.}" $stderr.puts e.backtrace.first(10).join("\n") raise end |
.generate_routes ⇒ Object
Internal: Generates TypeSpec routes from Rails routes
676 677 678 679 680 681 682 683 684 685 686 687 |
# File 'lib/typespec_from_serializers/generator.rb', line 676 def generate_routes return [] unless defined?(Rails) && Rails.application routes, controllers = collect_rails_routes cache_key = routes.map(&:inspect).join write_if_changed(filename: "routes", cache_key: cache_key) { routes_content(routes) } # Return list of controller class names controllers.sort end |
.loaded_serializers ⇒ Object
Public: Returns all loaded serializer classes.
Returns Array of serializer classes
724 725 726 727 728 729 730 731 732 733 |
# File 'lib/typespec_from_serializers/generator.rb', line 724 def loaded_serializers config.base_serializers.map(&:constantize) .flat_map(&:descendants) .uniq .reject { |s| s.name.nil? } # Filter out anonymous classes .sort_by(&:name) .reject { |s| skip_serializer?(s) } rescue NameError raise ArgumentError, "Please ensure all your serializers extend BaseSerializer, or configure `config.base_serializers`." end |
.rbi_dir ⇒ Object
Public: Returns the RBI base directory path.
Returns Pathname
717 718 719 |
# File 'lib/typespec_from_serializers/generator.rb', line 717 def rbi_dir root.join("sorbet/rbi") end |
.root ⇒ Object
Public: Returns the application root path.
Returns Pathname
710 711 712 |
# File 'lib/typespec_from_serializers/generator.rb', line 710 def root (defined?(Rails) && Rails.root) || Pathname.new(Dir.pwd) end |
.serializers ⇒ Object
Public: Returns all loaded serializers.
Returns Array of serializer classes.
703 704 705 |
# File 'lib/typespec_from_serializers/generator.rb', line 703 def serializers loaded_serializers end |
.skip_serializer?(serializer) ⇒ Boolean
Internal: Checks if it should avoid generating an model.
690 691 692 693 |
# File 'lib/typespec_from_serializers/generator.rb', line 690 def skip_serializer?(serializer) serializer.name.in?(config.base_serializers) || config.skip_serializer_if.call(serializer) end |
.track_changes ⇒ Object
Internal: Returns an object compatible with FileUpdateChecker.
696 697 698 |
# File 'lib/typespec_from_serializers/generator.rb', line 696 def track_changes changes end |