enroute 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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: []