diff --git a/playground/vanilla/Gemfile.lock b/playground/vanilla/Gemfile.lock index fab67be..fa75921 100644 --- a/playground/vanilla/Gemfile.lock +++ b/playground/vanilla/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../.. specs: - types_from_serializers (2.1.0) + types_from_serializers (2.2.0) listen (~> 3.2) oj_serializers (~> 2.0, >= 2.0.2) railties (>= 5.1) diff --git a/playground/vanilla/app/frontend/types/serializers/ComposerWithSongs.ts b/playground/vanilla/app/frontend/types/serializers/ComposerWithSongs.ts index 1ccb876..8111674 100644 --- a/playground/vanilla/app/frontend/types/serializers/ComposerWithSongs.ts +++ b/playground/vanilla/app/frontend/types/serializers/ComposerWithSongs.ts @@ -1,12 +1,12 @@ -// TypesFromSerializers CacheKey 1e3a5dea8847b2dcfe76fec134589cbb +// TypesFromSerializers CacheKey 9111c6d881174b0013582fa6366868db // // DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. -import type Model from './Model' +import type ComposerWithSongsSong from './ComposerWithSongs/Song' export default interface ComposerWithSongs { id: number firstName?: string lastName?: string name: string - songs: Model[] + songs: ComposerWithSongsSong[] } diff --git a/playground/vanilla/app/frontend/types/serializers/ComposerWithSongs/Song.ts b/playground/vanilla/app/frontend/types/serializers/ComposerWithSongs/Song.ts new file mode 100644 index 0000000..81dfc18 --- /dev/null +++ b/playground/vanilla/app/frontend/types/serializers/ComposerWithSongs/Song.ts @@ -0,0 +1,8 @@ +// TypesFromSerializers CacheKey a69c0dbcc904740e5de89181ef4b2837 +// +// DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. + +export default interface ComposerWithSongsSong { + id: number + title?: string +} diff --git a/playground/vanilla/app/frontend/types/serializers/Song.ts b/playground/vanilla/app/frontend/types/serializers/Song.ts index 28e7de8..fdfe5eb 100644 --- a/playground/vanilla/app/frontend/types/serializers/Song.ts +++ b/playground/vanilla/app/frontend/types/serializers/Song.ts @@ -1,4 +1,4 @@ -// TypesFromSerializers CacheKey 460b4a83a2e81c9d693ac5490f9e0b76 +// TypesFromSerializers CacheKey f4f9e398dc092747d13607e2bdcb0846 // // DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. import type Composer from './Composer' @@ -6,7 +6,7 @@ import type Composer from './Composer' export default interface Song { id: number composer: Composer - genre: "disco" | "rock" | "classical" + genre: "fingerstyle" | "rock" | "classical" tempo: "slow" | "medium" | "fast" title?: string } diff --git a/playground/vanilla/app/frontend/types/serializers/SongWithVideos.ts b/playground/vanilla/app/frontend/types/serializers/SongWithVideos.ts index c587ad9..8598518 100644 --- a/playground/vanilla/app/frontend/types/serializers/SongWithVideos.ts +++ b/playground/vanilla/app/frontend/types/serializers/SongWithVideos.ts @@ -1,4 +1,4 @@ -// TypesFromSerializers CacheKey 3aa811bd4673913bbd09f2967979b304 +// TypesFromSerializers CacheKey c2d167325e7342eba01d0a78482d6d76 // // DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. import type Composer from './Composer' @@ -7,7 +7,7 @@ import type Video from './Video' export default interface SongWithVideos { id: number composer: Composer - genre: "disco" | "rock" | "classical" + genre: "fingerstyle" | "rock" | "classical" tempo: "slow" | "medium" | "fast" title?: string videos: Video[] diff --git a/playground/vanilla/app/serializers/composer_with_songs_serializer.rb b/playground/vanilla/app/serializers/composer_with_songs_serializer.rb index 0b0f224..3558f68 100644 --- a/playground/vanilla/app/serializers/composer_with_songs_serializer.rb +++ b/playground/vanilla/app/serializers/composer_with_songs_serializer.rb @@ -1,3 +1,7 @@ class ComposerWithSongsSerializer < ComposerSerializer - has_many :songs, serializer: ModelSerializer + class SongSerializer < BaseSerializer + attributes(:id, :title) + end + + has_many :songs, serializer: SongSerializer end diff --git a/spec/types_from_serializers/__snapshots__/interfaces_ComposerWithSongsSerializer.snap b/spec/types_from_serializers/__snapshots__/interfaces_ComposerWithSongsSerializer.snap index 1ccb876..8111674 100644 --- a/spec/types_from_serializers/__snapshots__/interfaces_ComposerWithSongsSerializer.snap +++ b/spec/types_from_serializers/__snapshots__/interfaces_ComposerWithSongsSerializer.snap @@ -1,12 +1,12 @@ -// TypesFromSerializers CacheKey 1e3a5dea8847b2dcfe76fec134589cbb +// TypesFromSerializers CacheKey 9111c6d881174b0013582fa6366868db // // DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. -import type Model from './Model' +import type ComposerWithSongsSong from './ComposerWithSongs/Song' export default interface ComposerWithSongs { id: number firstName?: string lastName?: string name: string - songs: Model[] + songs: ComposerWithSongsSong[] } diff --git a/spec/types_from_serializers/__snapshots__/interfaces_ComposerWithSongsSerializer__SongSerializer.snap b/spec/types_from_serializers/__snapshots__/interfaces_ComposerWithSongsSerializer__SongSerializer.snap new file mode 100644 index 0000000..81dfc18 --- /dev/null +++ b/spec/types_from_serializers/__snapshots__/interfaces_ComposerWithSongsSerializer__SongSerializer.snap @@ -0,0 +1,8 @@ +// TypesFromSerializers CacheKey a69c0dbcc904740e5de89181ef4b2837 +// +// DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. + +export default interface ComposerWithSongsSong { + id: number + title?: string +} diff --git a/spec/types_from_serializers/__snapshots__/namespace_interfaces_ComposerWithSongsSerializer.snap b/spec/types_from_serializers/__snapshots__/namespace_interfaces_ComposerWithSongsSerializer.snap index 4ce7ac6..857d318 100644 --- a/spec/types_from_serializers/__snapshots__/namespace_interfaces_ComposerWithSongsSerializer.snap +++ b/spec/types_from_serializers/__snapshots__/namespace_interfaces_ComposerWithSongsSerializer.snap @@ -1,7 +1,7 @@ -// TypesFromSerializers CacheKey 1e3a5dea8847b2dcfe76fec134589cbb +// TypesFromSerializers CacheKey 9111c6d881174b0013582fa6366868db // // DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. -import type Model from './Model' +import type ComposerWithSongsSong from './ComposerWithSongs/Song' declare global { namespace Schema { @@ -10,7 +10,7 @@ declare global { firstName?: string lastName?: string name: string - songs: Model[] + songs: ComposerWithSongsSong[] } } } diff --git a/spec/types_from_serializers/__snapshots__/namespace_interfaces_ComposerWithSongsSerializer__SongSerializer.snap b/spec/types_from_serializers/__snapshots__/namespace_interfaces_ComposerWithSongsSerializer__SongSerializer.snap new file mode 100644 index 0000000..cf83be0 --- /dev/null +++ b/spec/types_from_serializers/__snapshots__/namespace_interfaces_ComposerWithSongsSerializer__SongSerializer.snap @@ -0,0 +1,13 @@ +// TypesFromSerializers CacheKey a69c0dbcc904740e5de89181ef4b2837 +// +// DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. +export {} + +declare global { + namespace Schema { + interface ComposerWithSongsSong { + id: number + title?: string + } + } +} diff --git a/spec/types_from_serializers/generator_spec.rb b/spec/types_from_serializers/generator_spec.rb index 1dd76ec..9353928 100644 --- a/spec/types_from_serializers/generator_spec.rb +++ b/spec/types_from_serializers/generator_spec.rb @@ -13,13 +13,14 @@ SongWithVideosSerializer ModelSerializer ComposerWithSongsSerializer + ComposerWithSongsSerializer::SongSerializer ComposerSerializer SnakeComposerSerializer ] } def file_for(dir, name, ext) - dir.join("#{name.chomp("Serializer").gsub("::", "/")}.#{ext}") + dir.join("#{TypesFromSerializers.config.name_from_serializer.call(name).gsub("::", "/")}.#{ext}") end def app_file_for(name, ext = "ts") diff --git a/types_from_serializers/lib/types_from_serializers/generator.rb b/types_from_serializers/lib/types_from_serializers/generator.rb index 7390ad8..af36426 100644 --- a/types_from_serializers/lib/types_from_serializers/generator.rb +++ b/types_from_serializers/lib/types_from_serializers/generator.rb @@ -38,6 +38,11 @@ def ts_filename TypesFromSerializers.config.name_from_serializer.call(name).gsub("::", "/") end + # Internal: If the serializer was defined inside a file. + def inline_serializer? + name.include?("Serializer::") + end + # Internal: The TypeScript properties of the serialzeir interface. def ts_properties @ts_properties ||= begin @@ -312,9 +317,7 @@ def generate_index_file # Internal: Checks if it should avoid generating an interface. def skip_serializer?(serializer) serializer.name.in?(config.base_serializers) || - config.skip_serializer_if.call(serializer) || - # NOTE: Ignore inline serializers. - serializer.ts_name.include?("Serializer") + config.skip_serializer_if.call(serializer) end # Internal: Returns an object compatible with FileUpdateChecker. @@ -362,7 +365,9 @@ def default_config(root) output_dir: root.join(defined?(ViteRuby) ? ViteRuby.config.source_code_dir : "app/frontend").join("types/serializers"), # Remove the serializer suffix from the class name. - name_from_serializer: ->(name) { name.delete_suffix("Serializer") }, + name_from_serializer: ->(name) { + name.split("::").map { |n| n.delete_suffix("Serializer") }.join("::") + }, # Types that don't need to be imported in TypeScript. global_types: [ @@ -420,7 +425,7 @@ def serializers_index_content(serializers) <<~TS // // DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. - #{serializers.map { |s| + #{serializers.reject(&:inline_serializer?).map { |s| "export type { default as #{s.ts_name} } from './#{s.ts_filename}'" }.join("\n")} TS