enroute 0.0.1 → 0.0.2

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: 69b21678657d7b4e22392bb0fc93d825146f9af0ff90bcdbc5e356e8492cfb14
4
- data.tar.gz: 3cef2464c5fbd9fa7e14a1a321e8a3f054c45ef4f92f9c1dd1814aeeaa0246ab
3
+ metadata.gz: 0a1933a0b54db509a086908e62c6c1c0cd32baa72fbeba4f2b19e180f179b7e0
4
+ data.tar.gz: 65cd118dfb50f62b13b43fc2fe6ec95f3ada98d0d15947a7261f2858ae8b4b83
5
5
  SHA512:
6
- metadata.gz: 8802edb40c7a1e1ca283bda49f8aa7eb1cc5e68dd13f0234b77a7dcd4f51310fd64fc57a9a6276e4383b4ce78ea691ac4ad53e8b878c7ed9278425936adbf455
7
- data.tar.gz: b96ce752c8b775de0b699e3368ef121e98cf66813a052db033084c2def29a54d9fad4d545ceee6cd7c2ae31b8f63393356e68c23b9faaa21d009391b8801b117
6
+ metadata.gz: 24398ef1734fe1964932aee1c3e5ea29efe4ff73a11e99612eadcc55579b31b0c8611e54e4a46a030059efbfcc597b4372d97fc856c62c420fb0dcb61f92419e
7
+ data.tar.gz: 23d765635d12a58a14a263cc5cbf595d814b4443a46fceef1fab4cd61b93519e86b0d2e74e526639abd93749f0e1764a8a9409dec4dba73bf0267f7393e92407
@@ -0,0 +1 @@
1
+ github: [fnando]
data/.gitignore CHANGED
@@ -8,4 +8,5 @@
8
8
  /tmp/
9
9
  /node_modules
10
10
  /test/enroute/routes.ts
11
+ /test/enroute/routes_with_config.ts
11
12
  *.lock
data/.rubocop.yml CHANGED
@@ -4,8 +4,7 @@ inherit_gem:
4
4
 
5
5
  AllCops:
6
6
  TargetRubyVersion: 2.7
7
+ NewCops: enable
7
8
 
8
- Metrics/BlockLength:
9
- Exclude:
10
- - test/**/*.rb
11
- - "*.gemspec"
9
+ Metrics:
10
+ Enabled: false
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- nodejs 12.16.0
1
+ nodejs 16.7.0
data/README.md CHANGED
@@ -25,16 +25,55 @@ All you have to do is call the `enroute` binary with the main file you want to
25
25
  load and a output path.
26
26
 
27
27
  ```console
28
- $ bundle exec enroute --output ./app/frontend/scripts/config/routes.ts
28
+ $ bundle exec enroute export --output ./app/frontend/scripts/config/routes.ts
29
29
  ```
30
30
 
31
31
  By default, `<pwd>/config/environment.rb` will be loaded. If you want to use a
32
32
  different file, use the `--require` switch.
33
33
 
34
34
  ```console
35
- $ bundle exec enroute --require ./different-file.rb --output ./routes.ts
35
+ $ bundle exec enroute export --require ./different-file.rb --output ./routes.ts
36
36
  ```
37
37
 
38
+ You can also ignore routes by using a config file.
39
+
40
+ ```console
41
+ $ bundle exec enroute export --output ./app/frontend/scripts/config/routes.ts --config ./config/enroute.yml
42
+ ```
43
+
44
+ The config file must look like this:
45
+
46
+ ```yaml
47
+ ---
48
+ ignore:
49
+ - route_name
50
+ ```
51
+
52
+ There's also a `:only` option that will include only the matching named routes.
53
+
54
+ ```yaml
55
+ ---
56
+ only:
57
+ - route_name
58
+ ```
59
+
60
+ By default, route params will be typed as `any`. To add a custom typing
61
+ annotation, you can use the `typings` key on the configuration file. Imagine you
62
+ have the route `get "settings/edit(/:section)" => "", as: "edit_settings"`; you
63
+ can have a config file like this:
64
+
65
+ ```yaml
66
+ ---
67
+ typings:
68
+ _default:
69
+ format: '"html" | "json"'
70
+
71
+ edit_settings:
72
+ section: string
73
+ ```
74
+
75
+ ### Importing helpers on TypeScript
76
+
38
77
  You can then import any route that's been exported. Parameters are positional.
39
78
 
40
79
  ```typescript
data/enroute.gemspec CHANGED
@@ -7,6 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.version = Enroute::VERSION
8
8
  spec.authors = ["Nando Vieira"]
9
9
  spec.email = ["me@fnando.com"]
10
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
10
11
 
11
12
  spec.summary = "Export Rails routes to TypeScript definitions"
12
13
  spec.description = spec.summary
@@ -27,9 +28,11 @@ Gem::Specification.new do |spec|
27
28
  spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f) }
28
29
  spec.require_paths = ["lib"]
29
30
 
31
+ spec.add_dependency "activesupport"
30
32
  spec.add_dependency "thor"
31
33
  spec.add_development_dependency "minitest"
32
34
  spec.add_development_dependency "minitest-utils"
35
+ spec.add_development_dependency "pry-meta"
33
36
  spec.add_development_dependency "rails"
34
37
  spec.add_development_dependency "rake"
35
38
  spec.add_development_dependency "rubocop"
data/lib/enroute/cli.rb CHANGED
@@ -24,12 +24,19 @@ module Enroute
24
24
  required: true,
25
25
  aliases: :o
26
26
 
27
+ option :config,
28
+ type: :string,
29
+ required: false,
30
+ aliases: :c,
31
+ default: File.join(Dir.pwd, "config/enroute.yml")
32
+
27
33
  def export
28
34
  require_path = File.expand_path(options["require"])
29
35
  output_path = File.expand_path(options["output"])
36
+ config_path = File.expand_path(options["config"])
30
37
 
31
38
  require require_path
32
- Export.call(output_path)
39
+ Export.call(output_path, config_path)
33
40
  end
34
41
  end
35
42
  end
@@ -1,25 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Enroute
4
- module Export
5
- extend self
4
+ class Export
5
+ attr_reader :output_path, :config_path
6
6
 
7
- def call(output_path)
8
- FileUtils.mkdir_p(File.dirname(output_path))
7
+ def self.call(output_path, config_path)
8
+ new(output_path, config_path).call
9
+ end
9
10
 
10
- write_template(output_path)
11
+ def initialize(output_path, config_path)
12
+ @output_path = output_path
13
+ @config_path = config_path
14
+ end
15
+
16
+ def config
17
+ @config ||= if File.file?(config_path)
18
+ ActiveSupport::HashWithIndifferentAccess.new(
19
+ YAML.load_file(config_path)
20
+ )
21
+ else
22
+ {}
23
+ end
11
24
  end
12
25
 
13
- def params
14
- {
15
- routes: routes,
16
- types: routes.map {|route| build_ts_definition(route) }.join("\n"),
17
- router_type: routes.map {|route| build_ts_route_definition(route) }.join
18
- }
26
+ def call
27
+ FileUtils.mkdir_p(File.dirname(output_path))
28
+
29
+ write_template(output_path)
19
30
  end
20
31
 
21
32
  def routes
22
- Routes.call
33
+ @routes ||= Routes.call(config)
23
34
  end
24
35
 
25
36
  def write_template(output_path)
@@ -30,50 +41,42 @@ module Enroute
30
41
 
31
42
  def route_functions
32
43
  routes
33
- .each_with_index
34
- .map {|route, index| build_ts_function(route, index) }
44
+ .map {|route| build_ts_route_function(route) }
35
45
  .join("\n\n")
36
46
  end
37
47
 
38
- def router_type_definitions
39
- routes.map {|route| build_ts_route_definition(route) }.join
40
- end
41
-
42
- def type_definitions
43
- routes.map {|route| build_ts_definition(route) }.join("\n")
48
+ def handler_functions
49
+ routes.map {|route| build_ts_handler_function(route) }.join("\n\n")
44
50
  end
45
51
 
46
52
  def render_template
47
53
  ERB.new(File.read("#{__dir__}/template.ts.erb")).result binding
48
54
  end
49
55
 
50
- def build_ts_definition(route)
51
- [
52
- "export interface #{route[:typeName]} extends RouteHandler {",
53
- " (#{build_ts_args_definition(route)}): string;",
54
- "}\n"
55
- ].join("\n")
56
- end
57
-
58
56
  def build_ts_args_definition(route)
59
57
  route[:segments].map do |segment|
58
+ type = route.dig(:typings, segment)&.chomp ||
59
+ config.dig(:typings, :_default, segment)&.chomp ||
60
+ "any"
61
+
60
62
  optional = route[:requiredSegments].include?(segment) ? "" : "?"
61
- "#{segment.camelize(:lower)}#{optional}: any"
63
+ "#{segment.camelize(:lower)}#{optional}: #{type}"
62
64
  end.join(", ")
63
65
  end
64
66
 
65
- def build_ts_function(route, index)
67
+ def build_ts_handler_function(route)
68
+ args = JSON.pretty_generate(route.except(:typings))
69
+ %[const #{route[:name]}Handler = buildRoute(#{args});]
70
+ end
71
+
72
+ def build_ts_route_function(route)
66
73
  args = build_ts_args_definition(route)
67
74
  segments = route[:segments].map {|segment| segment.camelize(:lower) }
68
75
 
69
76
  [
70
77
  %[export const #{route[:name]}Url = (#{args}): string =>],
71
- %[ routeHandlers[#{index}](#{segments.join(', ')});]
78
+ %[ #{route[:name]}Handler(#{segments.join(', ')});]
72
79
  ].join("\n")
73
80
  end
74
-
75
- def build_ts_route_definition(route)
76
- %[\n #{route[:name]}: #{route[:typeName]};]
77
- end
78
81
  end
79
82
  end
@@ -1,8 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Enroute
4
- module Routes
5
- extend self
4
+ class Routes
5
+ attr_reader :config
6
+
7
+ def self.call(config = {})
8
+ new(config).call
9
+ end
10
+
11
+ def initialize(config)
12
+ @config = config
13
+ end
6
14
 
7
15
  def call
8
16
  grouped_routes.each_with_object([]) do |(_pattern, routes), buffer|
@@ -17,12 +25,12 @@ module Enroute
17
25
  def build_payload(route)
18
26
  {
19
27
  name: route.name.camelize(:lower),
20
- typeName: "#{route.name.camelize}RouteHandler",
21
28
  incomingPattern: camelize_pattern(route),
22
29
  outgoingPattern: route.ast.to_s,
23
30
  method: reduce_methods(routes),
24
31
  segments: route.segments,
25
- requiredSegments: route.path.required_names
32
+ requiredSegments: route.path.required_names,
33
+ typings: config.dig(:typings, route.name) || {}
26
34
  }
27
35
  end
28
36
 
@@ -48,8 +56,24 @@ module Enroute
48
56
  end
49
57
 
50
58
  def filtered_routes
51
- routes.reject do |route|
52
- route.name =~ /rails|script/
59
+ only_conditions = config.fetch(:only, [])
60
+
61
+ # If `:only` has at least one item, then select matching routes.
62
+ # Otherwise, use all routes.
63
+ selected_routes = if only_conditions.empty?
64
+ routes
65
+ else
66
+ routes.select do |route|
67
+ only_conditions.include?(route.name)
68
+ end
69
+ end
70
+
71
+ # Filter out unnamed routes, Rails' internal routes, and anything present
72
+ # on `:ignore`.
73
+ selected_routes.reject do |route|
74
+ route.name.nil? ||
75
+ route.name.match?(/rails|script/) ||
76
+ config.fetch(:ignore, []).include?(route.name)
53
77
  end
54
78
  end
55
79
 
@@ -90,17 +90,10 @@ function generate(route: Route): RouteHelper {
90
90
  };
91
91
  }
92
92
 
93
- export type PrimitiveType = number | string | null | undefined | boolean;
94
- export type ArrayType = AnyObject[];
95
- export type AnyObject = PrimitiveType | ArrayType | ObjectType | any;
96
-
97
- export interface ObjectType {
98
- [key: string]: PrimitiveType | ArrayType | ObjectType;
99
- }
93
+ type PrimitiveType = number | string | null | undefined | boolean;
100
94
 
101
95
  export interface Route {
102
96
  name: string;
103
- typeName: string;
104
97
  pattern?: string;
105
98
  method: string[];
106
99
  segments: string[];
@@ -118,12 +111,6 @@ export type RouteHandler = RouteHelper & {
118
111
  underscore: RouteHelper;
119
112
  };
120
113
 
121
- <%= type_definitions %>
122
-
123
- export const routes: Route[] = <%= JSON.pretty_generate(routes) %>;
124
-
125
- export const routeHandlers: RouteHandler[] = [
126
- <%= routes.each_with_index.map {|route, index| %[ buildRoute(routes[#{index}]) as #{route[:typeName]},] }.join("\n") %>
127
- ];
114
+ <%= handler_functions %>
128
115
 
129
116
  <%= route_functions %>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Enroute
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  end
data/lib/enroute.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "thor"
4
+ require "active_support/core_ext/hash"
5
+ require "active_support/hash_with_indifferent_access"
4
6
  require "fileutils"
5
7
  require "erb"
6
8
  require "json"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enroute
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-14 00:00:00.000000000 Z
11
+ date: 2021-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: thor
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-meta
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rails
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -117,6 +145,7 @@ extensions: []
117
145
  extra_rdoc_files: []
118
146
  files:
119
147
  - ".eslintrc.json"
148
+ - ".github/FUNDING.yml"
120
149
  - ".gitignore"
121
150
  - ".prettierrc.js"
122
151
  - ".rubocop.yml"
@@ -138,7 +167,6 @@ files:
138
167
  - lib/enroute/version.rb
139
168
  - package.json
140
169
  - tsconfig.json
141
- - yarn.lock
142
170
  homepage: https://github.com/fnando/enroute
143
171
  licenses:
144
172
  - MIT
@@ -146,7 +174,7 @@ metadata:
146
174
  homepage_uri: https://github.com/fnando/enroute
147
175
  source_code_uri: https://github.com/fnando/enroute
148
176
  changelog_uri: https://github.com/fnando/enroute
149
- post_install_message:
177
+ post_install_message:
150
178
  rdoc_options: []
151
179
  require_paths:
152
180
  - lib
@@ -154,15 +182,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
182
  requirements:
155
183
  - - ">="
156
184
  - !ruby/object:Gem::Version
157
- version: '0'
185
+ version: 2.7.0
158
186
  required_rubygems_version: !ruby/object:Gem::Requirement
159
187
  requirements:
160
188
  - - ">="
161
189
  - !ruby/object:Gem::Version
162
190
  version: '0'
163
191
  requirements: []
164
- rubygems_version: 3.1.2
165
- signing_key:
192
+ rubygems_version: 3.2.22
193
+ signing_key:
166
194
  specification_version: 4
167
195
  summary: Export Rails routes to TypeScript definitions
168
196
  test_files: []