json_routes_webpack 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8da1c274608e8970d81bfe25abd56a85b95e7e15
4
+ data.tar.gz: d1a5b4e516f3c78eb5925d15cbf99f54f289452c
5
+ SHA512:
6
+ metadata.gz: a562d78537186d3bdbf691ff236efe970caba72d72079b3fe66640f9cea55c914d38a1455dddb28c5e42e165edd172a3fa6c45ef3c00cd61f938bd8312ad7a57
7
+ data.tar.gz: 209f7a54885316387b8836ab19d6150c37f6d40bed293d622c24940358950af19d056ae9c14d21fb67fa926883f90f9663ce20c292ac6a9b57a6ddc5b6fd7e3e
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ .idea/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ Gemfile.lock
15
+
16
+ node_modules/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,12 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.5
5
+ - 2.4.2
6
+ - ruby-head
7
+ cache:
8
+ bundler: true
9
+ install:
10
+ - bundle install
11
+ script:
12
+ - bundle exec rake spec
@@ -0,0 +1,11 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ <a name="0.1.1"></a>
6
+ ## [0.1.1](https://github.com/Alignable/json_routes_webpack/compare/v0.1.0...v0.1.1) (2017-11-12)
7
+
8
+
9
+
10
+ <a name="0.1.0"></a>
11
+ # 0.1.0 (2017-11-12)
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in json_routes_webpack.gemspec
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Alignable
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,88 @@
1
+ [![test][test]][test-url]
2
+ [![coverage][cover]][cover-url]
3
+
4
+ # JsonRoutesWebpack
5
+
6
+ Exports Rails named routes to JSON that can be loaded in Javascript via webpack loaders like [js-routes-loader](https://github.com/Alignable/js-routes-loader)
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'json_routes_webpack'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install json_routes_webpack
23
+
24
+ ## Usage
25
+
26
+ ### Add a Rails initializer
27
+
28
+ Add an initializer that configures the routes you want to export and the file to write them too
29
+
30
+ **config/initializers/json_routes_webpack.rb**
31
+ ```ruby
32
+ JsonRoutesWebpack.configure do |config|
33
+ config.add_routes 'app/javascript/generated/routes.json'
34
+ end
35
+ ```
36
+
37
+ In addition to the file name to write the routes `add_routes` supports two options arguments
38
+ * `include` - an array of regular expressions the route name must match to be included
39
+ * `exclude` - an array of regular expression tht the route name must not match
40
+
41
+ Example: suppose you wanted to export you app and admin routes to separate files
42
+ ```ruby
43
+ JsonRoutesWebpack.configure do |config|
44
+ config.add_routes 'app/javascript/routes/routes.json', exclude: [/admin/]
45
+ config.add_routes 'app/javascript/routes/admin_routes.json', include: [/admin/]
46
+ end
47
+ ```
48
+
49
+ ### Configure Rake to build json routes before Webpacker compiles
50
+
51
+ We need the json routes to be available to webpack loaders add a rake hook to build the routes before Webpacker compiles our javascript
52
+
53
+ **lib/tasks/js_routes.rake**
54
+ ```ruby
55
+ # generate json routes before webpacker so they can be used by loaders
56
+ if Rake::Task.task_defined?("webpacker:compile")
57
+ Rake::Task["webpacker:compile"].enhance ["json_routes_webpack:compile"]
58
+ end
59
+ ```
60
+
61
+ ### Install `js-routes-loader` and configure Webpacker to use it for routes json files
62
+
63
+ ```bash
64
+ $ yarn add js-routes-loader
65
+ ```
66
+
67
+ **config/webpack/environment.js**
68
+ ```javascript
69
+ const { environment } = require('@rails/webpacker');
70
+
71
+ environment.loaders.set('js-routes', {
72
+ test: /routes\.json$/,
73
+ use: 'js-routes-loader',
74
+ });
75
+
76
+ module.exports = environment;
77
+ ```
78
+
79
+
80
+ ## License
81
+
82
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
83
+
84
+ [test]: http://img.shields.io/travis/Alignable/json_routes_webpack.svg
85
+ [test-url]: https://travis-ci.org/Alignable/json_routes_webpack
86
+
87
+ [cover]: https://codecov.io/gh/Alignable/json_routes_webpack/branch/master/graph/badge.svg
88
+ [cover-url]: https://codecov.io/gh/Alignable/json_routes_webpack
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "json_routes_webpack"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,32 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "json_routes_webpack/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "json_routes_webpack"
8
+ spec.version = JsonRoutesWebpack::VERSION
9
+ spec.authors = ["Jon Palmer"]
10
+ spec.email = ["jon@alignable.com"]
11
+
12
+ spec.summary = %q{Export rails routes to json for webpack js-route-loader }
13
+ spec.description = %q{COnvert Ruby on Rails routes to webpack js-route-loader format and export to a json file.}
14
+ spec.homepage = "https://github.com/Alignable/json_routes_webpack"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_runtime_dependency "railties", ">= 5.1"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.16"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_development_dependency "rspec-mocks", "~> 3.0"
30
+ spec.add_development_dependency "simplecov"
31
+ spec.add_development_dependency "codecov"
32
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_routes_webpack/version"
4
+ require "json_routes_webpack/configuration"
5
+ require "json_routes_webpack/generator"
6
+
7
+ require "json_routes_webpack/railtie" if defined?(Rails)
8
+
9
+ module JsonRoutesWebpack
10
+ class << self
11
+ attr_writer :configuration
12
+ end
13
+
14
+ def self.configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def self.configure
19
+ yield(configuration)
20
+ end
21
+
22
+ def self.reset
23
+ @configuration = Configuration.new
24
+ end
25
+
26
+ def self.compile
27
+ JsonRoutesWebpack.configuration.generators.each(&:generate!)
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_routes_webpack"
4
+
5
+ module JsonRoutesWebpack
6
+ class Configuration
7
+ attr_reader :generators
8
+
9
+ def initialize
10
+ @generators = []
11
+ end
12
+
13
+ def add_routes(file, routes: nil, include: nil, exclude: nil)
14
+ @generators.push JsonRoutesWebpack::Generator.new(file, routes: routes, include: include, exclude: exclude)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/application"
4
+ require "action_dispatch/routing/inspector"
5
+
6
+ module JsonRoutesWebpack
7
+ class Generator
8
+ # @return [String]
9
+ attr_reader :file
10
+
11
+ # @return [ActionDispatch::Routing::RouteSet]
12
+ attr_reader :routes
13
+
14
+ # @return [Array<Regexp>,nil] default to nil
15
+ attr_reader :include
16
+
17
+ # @return [Array<Regexp>,nil] default to nil
18
+ attr_reader :exclude
19
+
20
+ def initialize(file, routes: nil, include: nil, exclude: nil)
21
+ @file = file
22
+ @routes = routes || Rails.application.routes.routes
23
+ @include = include
24
+ @exclude = exclude
25
+ end
26
+
27
+ # Generate a hash of all the route definitions matching the include and exclude rules
28
+ # and write the hash as json to the configured file
29
+ #
30
+ # @return [Hash]
31
+ def generate!
32
+ out_file = Rails.root.join(file)
33
+
34
+ dirname = File.dirname(out_file)
35
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
36
+
37
+ File.open(out_file, "w") do |f|
38
+ f.write(JSON.fast_generate(generate))
39
+ # f.write(source.to_json)
40
+ end
41
+ end
42
+
43
+ # Generate a hash of all the route definitions matching the include and exclude rules
44
+ #
45
+ # @return [Hash]
46
+ def generate
47
+ Rails.application.reload_routes!
48
+ all_routes = collect_routes(routes)
49
+ group_routes = group_routes(all_routes)
50
+ routes_to_display = filter_routes(group_routes)
51
+ { routes: routes_to_display }
52
+ end
53
+
54
+ private
55
+
56
+ # collect the routes, including nested engine routes, and build the summaries we need for the json
57
+ #
58
+ # @param routes [Array<ActionDispatch::Routing::RouteSet>]
59
+ # @param parent_route [ActionDispatch::Routing::RouteWrapper]
60
+ # @return [Array<Hash>]
61
+ def collect_routes(routes, parent_route = nil)
62
+ routes.map do |route|
63
+ ActionDispatch::Routing::RouteWrapper.new(route)
64
+ end.reject(&:internal?)
65
+ .flat_map do |route|
66
+ route.engine? ? collect_engine_routes(route) : build_route_summary(route, parent_route)
67
+ end
68
+ end
69
+
70
+ # merge the parent_route with the route returing a hash of properties that we need for the json
71
+ #
72
+ # @param route [ActionDispatch::Routing::RouteWrapper]
73
+ # @param parent_route [ActionDispatch::Routing::RouteWrapper]
74
+ # @return [Array<Hash>]
75
+ def build_route_summary(route, parent_route = nil)
76
+ name = [parent_route&.name, route.name].compact.join("_")
77
+ method = parent_route&.verb.presence || route.verb
78
+ path = "#{parent_route&.path}#{route.path}"
79
+ required_parts = [parent_route&.required_parts, route.required_parts].compact.flatten
80
+ parts = [parent_route&.parts, route.parts].compact.flatten
81
+
82
+ {
83
+ name: name,
84
+ method: method,
85
+ path: path,
86
+ required_parts: required_parts,
87
+ parts: parts
88
+ }
89
+ end
90
+
91
+ # collect the routes associate with the engine route
92
+ #
93
+ # @param routes [ActionDispatch::Routing::RouteWrapper]
94
+ # @return [Array<Hash>, nil]
95
+ def collect_engine_routes(route)
96
+ return unless route.engine?
97
+
98
+ routes = route.rack_app.routes
99
+ if routes.is_a?(ActionDispatch::Routing::RouteSet)
100
+ collect_routes(routes.routes, route)
101
+ end
102
+ end
103
+
104
+ # apply the include and exclude matchers
105
+ #
106
+ # @param routes [Array<Hash>]
107
+ # @return [Array<Hash>]
108
+ def filter_routes(routes)
109
+ routes.reject do |route|
110
+ (exclude && any_match?(route, exclude)) || (include && !any_match?(route, include))
111
+ end
112
+ end
113
+
114
+ # decide if the route matches any of the matchers
115
+ #
116
+ # @param route [Hash]
117
+ # @param matchers [Array<Regexp>]
118
+ # @return [bool]
119
+ def any_match?(route, matchers)
120
+ matchers.any? { |pattern| route[:name] =~ pattern }
121
+ end
122
+
123
+ # group the routes by path, aggregate all the supported methods and compute the optional params
124
+ #
125
+ # @param routes [Array<Hash>]
126
+ # @return [Array<Hash>]
127
+ def group_routes(routes)
128
+ routes.group_by do |route|
129
+ route[:path]
130
+ end.map do |path, route_group|
131
+ methods = route_group.map { |route| route[:method] }
132
+ named_route = route_group.find { |route| route[:name].present? } # only one of the grouped routes will have a name
133
+ if named_route
134
+ {
135
+ name: named_route[:name],
136
+ methods: methods,
137
+ path: named_route[:path],
138
+ required_params: named_route[:required_parts],
139
+ optional_params: named_route[:parts] - named_route[:required_parts]
140
+ }
141
+ end
142
+ end.compact
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_routes_webpack"
4
+ require "rails"
5
+
6
+ module JsonRoutesWebpack
7
+ class Railtie < Rails::Railtie
8
+ railtie_name :json_routes_webpack
9
+
10
+ rake_tasks do
11
+ load "tasks/json_routes_webpack.rake"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonRoutesWebpack
4
+ VERSION = "0.1.1"
5
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true.
2
+
3
+ namespace :json_routes_webpack do
4
+ desc "Export app routes to json format"
5
+ task compile: :environment do
6
+ JsonRoutesWebpack.compile
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "json_routes_webpack",
3
+ "version": "0.1.1",
4
+ "scripts": {
5
+ "release": "standard-version -a"
6
+ },
7
+ "standard-version": {
8
+ "scripts": {
9
+ "postbump": "gem bump --no-commit -v `node -p -e \"require('./package.json').version\"`",
10
+ "precommit": "git add -f lib/json_routes_webpack/version.rb"
11
+ }
12
+ },
13
+ "devDependencies": {
14
+ "standard-version": "^4.2.0"
15
+ }
16
+ }
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json_routes_webpack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Jon Palmer
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-11-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-mocks
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: codecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: COnvert Ruby on Rails routes to webpack js-route-loader format and export
112
+ to a json file.
113
+ email:
114
+ - jon@alignable.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - ".travis.yml"
122
+ - CHANGELOG.md
123
+ - Gemfile
124
+ - LICENSE
125
+ - README.md
126
+ - Rakefile
127
+ - bin/console
128
+ - bin/setup
129
+ - json_routes_webpack.gemspec
130
+ - lib/json_routes_webpack.rb
131
+ - lib/json_routes_webpack/configuration.rb
132
+ - lib/json_routes_webpack/generator.rb
133
+ - lib/json_routes_webpack/railtie.rb
134
+ - lib/json_routes_webpack/version.rb
135
+ - lib/tasks/json_routes_webpack.rake
136
+ - package.json
137
+ homepage: https://github.com/Alignable/json_routes_webpack
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.5.2
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Export rails routes to json for webpack js-route-loader
161
+ test_files: []